├── examples ├── l2fwd │ ├── vagrant │ │ ├── l2fwd │ │ │ ├── 50-memlock.conf │ │ │ ├── setup_experiment.sh │ │ │ └── Vagrantfile │ │ ├── client │ │ │ ├── setup_experiment.sh │ │ │ └── Vagrantfile │ │ ├── server │ │ │ ├── setup_experiment.sh │ │ │ └── Vagrantfile │ │ └── README.md │ └── l2fwd.go ├── dumpframes │ ├── ebpf │ │ ├── Makefile │ │ ├── include │ │ │ ├── Makefile │ │ │ └── bpf │ │ │ │ ├── bpf_helpers.h │ │ │ │ └── bpf_endian.h │ │ ├── Dockerfile │ │ ├── ipproto.go │ │ ├── single_protocol_filter.go │ │ ├── single_protocol_filter.c │ │ ├── ipproto_bpfeb.go │ │ └── ipproto_bpfel.go │ └── dumpframes.go ├── senddnsqueries │ └── senddnsqueries.go ├── sendudp │ └── sendudp.go └── rebroadcast │ └── rebroadcast.go ├── go.mod ├── .gitignore ├── .github └── workflows │ └── build.yaml ├── LICENSE ├── README.md ├── go.sum ├── program.go └── xdp.go /examples/l2fwd/vagrant/l2fwd/50-memlock.conf: -------------------------------------------------------------------------------- 1 | * - memlock 1048576 2 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/Makefile: -------------------------------------------------------------------------------- 1 | docker: 2 | docker build -t ebpf-generate -f Dockerfile . 3 | 4 | generate: 5 | docker run -i -t -v $$(pwd)/../../../:/target ebpf-generate 6 | -------------------------------------------------------------------------------- /examples/l2fwd/vagrant/client/setup_experiment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | nmcli d set eth1 managed no 4 | ip addr add 192.168.100.10/24 dev eth1 5 | ip route del default 6 | ip route add default via 192.168.100.1 dev eth1 7 | arp -s 192.168.100.1 08:00:27:fa:88:24 8 | -------------------------------------------------------------------------------- /examples/l2fwd/vagrant/server/setup_experiment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | nmcli d set eth1 managed no 4 | ip addr add 192.168.200.10/24 dev eth1 5 | ip route del default 6 | ip route add default via 192.168.200.1 dev eth1 7 | arp -s 192.168.200.1 08:00:27:c5:9c:11 8 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/slavc/xdp 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/cilium/ebpf v0.4.0 7 | github.com/google/gopacket v1.1.19 8 | github.com/miekg/dns v1.1.35 9 | github.com/vishvananda/netlink v1.1.0 10 | golang.org/x/sys v0.1.0 11 | ) 12 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/include/Makefile: -------------------------------------------------------------------------------- 1 | LINUX_INC ?= /usr/include 2 | LIBBPF_INC ?= /usr/local/include 3 | 4 | .PHONY: update 5 | update: 6 | rsync --existing --exclude "types.h" -av "$(LINUX_INC)/linux/" "$(CURDIR)/linux" 7 | rsync --existing -av "$(LIBBPF_INC)/bpf/" "$(CURDIR)/bpf" 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Developer 15 | .vscode 16 | 17 | # ebpf binaries 18 | *.o 19 | 20 | -------------------------------------------------------------------------------- /examples/l2fwd/vagrant/l2fwd/setup_experiment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | nmcli d set eth1 managed no 4 | nmcli d set eth2 managed no 5 | ip addr flush eth1 6 | ip addr add 192.168.100.1/24 dev eth1 7 | ip addr flush eth2 8 | ip addr add 192.168.200.1/24 dev eth2 9 | 10 | for ifi in eth1 eth2; do 11 | for opt in gro lro tso gso; do 12 | ethtool -K $ifi $opt off 13 | done 14 | done 15 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build & Test 2 | on: 3 | push: 4 | branches: 5 | - master 6 | tags: 7 | - 'v[0-9]+\.[0-9]+\.[0-9]+' 8 | pull_request: 9 | branches: 10 | - master 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | go: [1.17.x] 18 | steps: 19 | - uses: actions/checkout@v2 20 | - name: Setup Go environment (${{ matrix.go }}) 21 | uses: actions/setup-go@v2.2.0 22 | with: 23 | go-version: ${{ matrix.go }} 24 | - run: go build ./... 25 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:8 2 | 3 | RUN dnf install -y make cmake gcc gdb clang llvm clang-devel llvm-devel autoconf libtool kernel-devel libbpf elfutils-libelf-devel elfutils-devel 4 | 5 | RUN /bin/bash -c " \ 6 | curl -fsSL https://golang.org/dl/go1.16.2.linux-amd64.tar.gz -o /tmp/golang.tar.gz && \ 7 | tar -C /usr/local -xzf /tmp/golang.tar.gz" 8 | 9 | ENV PATH=$PATH:/usr/local/go/bin:/root/go/bin/ 10 | 11 | RUN dnf -y install git 12 | 13 | RUN go get github.com/cilium/ebpf/cmd/bpf2go@v0.4.0 14 | 15 | ENTRYPOINT ["bash", "-c", "cd /target/examples/dumpframes/ebpf && go generate"] 16 | -------------------------------------------------------------------------------- /examples/l2fwd/vagrant/server/Vagrantfile: -------------------------------------------------------------------------------- 1 | $provision_script = <<-SCRIPT 2 | echo Installing iperf... 3 | sudo dnf -y install iperf tcpdump 4 | echo Setting up the experiment... 5 | sudo ./setup_experiment.sh 6 | echo Done. 7 | echo 'Run `iperf -s` to start iperf server.' 8 | SCRIPT 9 | 10 | Vagrant.configure("2") do |config| 11 | config.vm.box = "fedora/30-cloud-base" 12 | config.vm.hostname = "server" 13 | config.vm.provider "virtualbox" do |v| 14 | v.name = "Server" 15 | v.memory = 1024 16 | #v.cpus = 2 17 | end 18 | config.vm.network "private_network", 19 | virtualbox__intnet: "server_intnet", 20 | mac: "0800270c57be", 21 | ip: "192.168.200.10", 22 | netmask: 24 23 | config.vm.provision "file", source: "setup_experiment.sh", destination: "setup_experiment.sh" 24 | config.vm.provision "shell", inline: $provision_script 25 | end 26 | -------------------------------------------------------------------------------- /examples/l2fwd/vagrant/client/Vagrantfile: -------------------------------------------------------------------------------- 1 | $provision_script = <<-SCRIPT 2 | echo Installing packages... 3 | sudo dnf -y install iperf tcpdump 4 | echo Setting up the experiment... 5 | sudo ./setup_experiment.sh 6 | echo Done. 7 | echo 'Run `iperf -t 120 -i 1 -e -c 192.168.200.10` to start iperf client.' 8 | SCRIPT 9 | 10 | Vagrant.configure("2") do |config| 11 | config.vm.box = "fedora/30-cloud-base" 12 | config.vm.hostname = "client" 13 | config.vm.provider "virtualbox" do |v| 14 | v.name = "Client" 15 | v.memory = 1024 16 | #v.cpus = 2 17 | end 18 | config.vm.network "private_network", 19 | virtualbox__intnet: "client_intnet", 20 | mac: "080027bdaa9b", 21 | ip: "192.168.100.10", 22 | netmask: 24 23 | config.vm.provision "file", source: "setup_experiment.sh", destination: "setup_experiment.sh" 24 | config.vm.provision "shell", inline: $provision_script 25 | end 26 | -------------------------------------------------------------------------------- /examples/l2fwd/vagrant/README.md: -------------------------------------------------------------------------------- 1 | # l2fwd test environment 2 | 3 | This directory contains Vagrant configuration files which will bring up a test 4 | environment for [l2fwd](https://github.com/slavc/xdp/examples/l2fwd/l2fwd.go). 5 | 6 | The enviornment consists of 3 virtual machines, 'Server', where you run the 7 | `iperf` server, 'Client' where you run the `iperf` client and 'L2fwd', where 8 | you run `l2fwd`. 9 | 10 | 'Client' and 'Server', in addition to the usual NAT interface, each have their 11 | own additional 'Internal Network' interface. 12 | 'L2fwd' has two additional 'Internal Network' interfaces, one in 'Client' 13 | network and one in 'Server' network. Thus 'L2fwd' is able to bridge the 14 | networks between 'Client' and 'Server'. 15 | 16 | # How to deploy 17 | 18 | 1. Install Vagrant, e.g. on Fedora Linux: `sudo dnf install vagrant`. 19 | 2. Run `vagrant up` in each of the `server`, `client` and `l2fwd` directories. 20 | 3. Log into each machine by running `vagrant ssh` in corresponding directory 21 | and run the command that was printed at the end of provisioning in previous 22 | step. 23 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/ipproto.go: -------------------------------------------------------------------------------- 1 | // +build !armbe,!arm64be,!mips,!mips64,!mips64p32,!ppc64,!s390,!s390x,!sparc,!sparc64,!386,!amd64,!amd64p32,!arm,!arm64,!mipsle,!mips64le,!mips64p32le,!ppc64le,!riscv6 2 | 3 | package ebpf 4 | 5 | import ( 6 | "github.com/cilium/ebpf" 7 | ) 8 | 9 | func loadIpproto() (*ebpf.CollectionSpec, error) { 10 | panic("unimplemented") 11 | } 12 | 13 | func loadIpprotoObjects(obj interface{}, opts *ebpf.CollectionOptions) error { 14 | panic("unimplemented") 15 | } 16 | 17 | type ipprotoSpecs struct { 18 | ipprotoProgramSpecs 19 | ipprotoMapSpecs 20 | } 21 | 22 | type ipprotoProgramSpecs struct { 23 | XdpSockProg *ebpf.ProgramSpec `ebpf:"xdp_sock_prog"` 24 | } 25 | 26 | type ipprotoMapSpecs struct { 27 | QidconfMap *ebpf.MapSpec `ebpf:"qidconf_map"` 28 | XsksMap *ebpf.MapSpec `ebpf:"xsks_map"` 29 | } 30 | 31 | type ipprotoObjects struct { 32 | ipprotoPrograms 33 | ipprotoMaps 34 | } 35 | 36 | type ipprotoMaps struct { 37 | QidconfMap *ebpf.Map `ebpf:"qidconf_map"` 38 | XsksMap *ebpf.Map `ebpf:"xsks_map"` 39 | } 40 | 41 | type ipprotoPrograms struct { 42 | XdpSockProg *ebpf.Program `ebpf:"xdp_sock_prog"` 43 | } 44 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/single_protocol_filter.go: -------------------------------------------------------------------------------- 1 | package ebpf 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/slavc/xdp" 7 | "github.com/cilium/ebpf" 8 | ) 9 | 10 | // go generate requires appropriate linux headers in included (-I) paths. 11 | // See accompanying Makefile + Dockerfile to make updates. 12 | //go:generate $HOME/go/bin/bpf2go ipproto single_protocol_filter.c -- -I/usr/include/ -I./include -nostdinc -O3 13 | 14 | // NewIPProtoProgram returns an new eBPF that directs packets of the given ip protocol to to XDP sockets 15 | func NewIPProtoProgram(protocol uint32, options *ebpf.CollectionOptions) (*xdp.Program, error) { 16 | spec, err := loadIpproto() 17 | if err != nil { 18 | return nil, err 19 | } 20 | 21 | if protocol >= 0 && protocol <= 255 { 22 | if err := spec.RewriteConstants(map[string]interface{}{"PROTO": uint8(protocol)}); err != nil { 23 | return nil, err 24 | } 25 | } else { 26 | return nil, fmt.Errorf("protocol must be between 0 and 255") 27 | } 28 | var program ipprotoObjects 29 | if err := spec.LoadAndAssign(&program, options); err != nil { 30 | return nil, err 31 | } 32 | 33 | p := &xdp.Program{Program: program.XdpSockProg, Queues: program.QidconfMap, Sockets: program.XsksMap} 34 | return p, nil 35 | } 36 | -------------------------------------------------------------------------------- /examples/l2fwd/vagrant/l2fwd/Vagrantfile: -------------------------------------------------------------------------------- 1 | $provision_script = <<-SCRIPT 2 | echo Installing packages... 3 | sudo dnf -y install golang ethtool tcpdump perf vim 4 | echo Fetching and building l2fwd... 5 | go get github.com/slavc/xdp/examples/l2fwd 6 | echo Increasing maximum locked memory size... 7 | sudo install 50-memlock.conf /etc/security/limits.d/50-memlock.conf 8 | echo Setting up the experiment... 9 | sudo ./setup_experiment.sh 10 | echo Done. 11 | echo 'Run `sudo ~/go/bin/l2fwd -verbose -inlink eth1 -outlink eth2 -inlinkdst 08:00:27:0c:57:be -outlinkdst 08:00:27:bd:aa:9b` to start l2fwd.' 12 | SCRIPT 13 | 14 | Vagrant.configure("2") do |config| 15 | config.vm.box = "fedora/30-cloud-base" 16 | config.vm.hostname = "l2fwd" 17 | config.vm.provider "virtualbox" do |v| 18 | v.name = "L2fwd" 19 | v.memory = 1024 20 | #v.cpus = 2 21 | end 22 | config.vm.network "private_network", 23 | virtualbox__intnet: "client_intnet", 24 | mac: "080027fa8824", 25 | ip: "192.168.100.1", 26 | netmask: 24 27 | config.vm.network "private_network", 28 | virtualbox__intnet: "server_intnet", 29 | mac: "080027c59c11", 30 | ip: "192.168.200.1", 31 | netmask: 24 32 | config.vm.provision "file", source: "50-memlock.conf", destination: "50-memlock.conf" 33 | config.vm.provision "file", source: "setup_experiment.sh", destination: "setup_experiment.sh" 34 | config.vm.provision "shell", inline: $provision_script 35 | end 36 | 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Asavie Technologies Ltd 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/include/bpf/bpf_helpers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __BPF_HELPERS__ 3 | #define __BPF_HELPERS__ 4 | 5 | /* 6 | * Note that bpf programs need to include either 7 | * vmlinux.h (auto-generated from BTF) or linux/types.h 8 | * in advance since bpf_helper_defs.h uses such types 9 | * as __u64. 10 | */ 11 | #include "bpf_helper_defs.h" 12 | 13 | #define __uint(name, val) int (*name)[val] 14 | #define __type(name, val) typeof(val) *name 15 | #define __array(name, val) typeof(val) *name[] 16 | 17 | /* Helper macro to print out debug messages */ 18 | #define bpf_printk(fmt, ...) \ 19 | ({ \ 20 | char ____fmt[] = fmt; \ 21 | bpf_trace_printk(____fmt, sizeof(____fmt), \ 22 | ##__VA_ARGS__); \ 23 | }) 24 | 25 | /* 26 | * Helper macro to place programs, maps, license in 27 | * different sections in elf_bpf file. Section names 28 | * are interpreted by elf_bpf loader 29 | */ 30 | #define SEC(NAME) __attribute__((section(NAME), used)) 31 | 32 | #ifndef __always_inline 33 | #define __always_inline __attribute__((always_inline)) 34 | #endif 35 | #ifndef __weak 36 | #define __weak __attribute__((weak)) 37 | #endif 38 | 39 | /* 40 | * Helper macro to manipulate data structures 41 | */ 42 | #ifndef offsetof 43 | #define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) 44 | #endif 45 | #ifndef container_of 46 | #define container_of(ptr, type, member) \ 47 | ({ \ 48 | void *__mptr = (void *)(ptr); \ 49 | ((type *)(__mptr - offsetof(type, member))); \ 50 | }) 51 | #endif 52 | 53 | /* 54 | * Helper structure used by eBPF C program 55 | * to describe BPF map attributes to libbpf loader 56 | */ 57 | struct bpf_map_def { 58 | unsigned int type; 59 | unsigned int key_size; 60 | unsigned int value_size; 61 | unsigned int max_entries; 62 | unsigned int map_flags; 63 | }; 64 | 65 | enum libbpf_pin_type { 66 | LIBBPF_PIN_NONE, 67 | /* PIN_BY_NAME: pin maps by name (in /sys/fs/bpf by default) */ 68 | LIBBPF_PIN_BY_NAME, 69 | }; 70 | 71 | enum libbpf_tristate { 72 | TRI_NO = 0, 73 | TRI_YES = 1, 74 | TRI_MODULE = 2, 75 | }; 76 | 77 | #define __kconfig __attribute__((section(".kconfig"))) 78 | #define __ksym __attribute__((section(".ksyms"))) 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/single_protocol_filter.c: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | #define MAX_SOCKS 64 14 | 15 | static volatile unsigned const char PROTO; 16 | static volatile unsigned const char PROTO = IPPROTO_ICMP; 17 | 18 | //Ensure map references are available. 19 | /* 20 | These will be initiated from go and 21 | referenced in the end BPF opcodes by file descriptor 22 | */ 23 | 24 | struct bpf_map_def SEC("maps") xsks_map = { 25 | .type = BPF_MAP_TYPE_XSKMAP, 26 | .key_size = sizeof(int), 27 | .value_size = sizeof(int), 28 | .max_entries = MAX_SOCKS, 29 | }; 30 | 31 | struct bpf_map_def SEC("maps") qidconf_map = { 32 | .type = BPF_MAP_TYPE_ARRAY, 33 | .key_size = sizeof(int), 34 | .value_size = sizeof(int), 35 | .max_entries = MAX_SOCKS, 36 | }; 37 | 38 | 39 | SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx) 40 | { 41 | 42 | int *qidconf, index = ctx->rx_queue_index; 43 | 44 | // A set entry here means that the correspnding queue_id 45 | // has an active AF_XDP socket bound to it. 46 | qidconf = bpf_map_lookup_elem(&qidconf_map, &index); 47 | if (!qidconf) 48 | return XDP_PASS; 49 | 50 | // redirect packets to an xdp socket that match the given IPv4 or IPv6 protocol; pass all other packets to the kernel 51 | void *data = (void*)(long)ctx->data; 52 | void *data_end = (void*)(long)ctx->data_end; 53 | struct ethhdr *eth = data; 54 | __u16 h_proto = eth->h_proto; 55 | if ((void*)eth + sizeof(*eth) <= data_end) { 56 | if (bpf_htons(h_proto) == ETH_P_IP) { 57 | struct iphdr *ip = data + sizeof(*eth); 58 | if ((void*)ip + sizeof(*ip) <= data_end) { 59 | if (ip->protocol == PROTO) { 60 | if (*qidconf) 61 | return bpf_redirect_map(&xsks_map, index, 0); 62 | } 63 | } 64 | } else if (bpf_htons(h_proto) == ETH_P_IPV6) { 65 | struct ipv6hdr *ip = data + sizeof(*eth); 66 | if ((void*)ip + sizeof(*ip) <= data_end) { 67 | if (ip->nexthdr == PROTO) { 68 | if (*qidconf) 69 | return bpf_redirect_map(&xsks_map, index, 0); 70 | } 71 | } 72 | } 73 | } 74 | 75 | return XDP_PASS; 76 | } 77 | 78 | //Basic license just for compiling the object code 79 | char __license[] SEC("license") = "LGPL-2.1 or BSD-2-Clause"; 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xdp 2 | 3 | [![Go Reference](https://pkg.go.dev/badge/github.com/slavc/xdp.svg)](https://pkg.go.dev/github.com/slavc/xdp) 4 | 5 | Package github.com/slavc/xdp allows one to use [XDP sockets](https://lwn.net/Articles/750845/) from the Go programming language. 6 | 7 | For usage examples, see the [documentation](https://pkg.go.dev/github.com/slavc/xdp) or the [examples/](https://github.com/slavc/xdp/tree/master/examples) directory. 8 | 9 | ## Performance 10 | 11 | ### examples/sendudp 12 | 13 | With the default UDP payload size of 1400 bytes, running on Linux kernel 14 | 5.1.20, on a 15 | [tg3](https://github.com/torvalds/linux/blob/master/drivers/net/ethernet/broadcom/tg3.c) 16 | (so no native XDP support) gigabit NIC, 17 | [sendudp.go](https://github.com/slavc/xdp/blob/master/examples/sendudp/sendudp.go) 18 | does around 980 Mb/s, so practically line rate. 19 | 20 | ### examples/senddnsqueries 21 | 22 | TL;DR: in the same environment, sending a pre-generated DNS query using an 23 | ordinary UDP socket yields around 30 MiB/s whereas sending it using the 24 | [senddnsqueries.go](https://github.com/slavc/xdp/blob/master/examples/senddnsqueries/senddnsqueries.go) 25 | example program yields around 77 MiB/s. 26 | 27 | Connecting a PC with Intel Core i7-7700 CPU running Linux kernel 5.0.17 and igb 28 | driver to a laptop with Intel Core i7-5600U CPU running Linux kernel 5.0.9 with 29 | e1000e with a cat 5E gigabit ethernet cable and using the following program 30 | ```go 31 | package main 32 | 33 | import ( 34 | "net" 35 | 36 | "github.com/miekg/dns" 37 | ) 38 | 39 | func main() { 40 | query := new(dns.Msg) 41 | query.SetQuestion(dns.Fqdn("slavc.com"), dns.TypeA) 42 | payload, err := query.Pack() 43 | if err != nil { 44 | panic(err) 45 | } 46 | 47 | conn, err := net.ListenPacket("udp", ":0") 48 | if err != nil { 49 | panic(err) 50 | } 51 | defer conn.Close() 52 | 53 | dst, err := net.ResolveUDPAddr("udp", "192.168.111.10:53") 54 | if err != nil { 55 | panic(err) 56 | } 57 | 58 | for { 59 | _, err = conn.WriteTo(payload, dst) 60 | if err != nil { 61 | panic(err) 62 | } 63 | } 64 | } 65 | ``` 66 | which uses an ordinary UDP socket to send a pre-generated DNS query from PC to 67 | laptop as quickly as possible - I get about 30 MiB/s at laptop side. 68 | 69 | Using the [senddnsqueries.go](https://github.com/slavc/xdp/blob/master/examples/senddnsqueries/senddnsqueries.go) 70 | example program - I get about 77 MiB/s at laptop side. 71 | 72 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/cilium/ebpf v0.4.0 h1:QlHdikaxALkqWasW8hAC1mfR0jdmvbfaBdBPFmRSglA= 2 | github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= 3 | github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= 4 | github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= 5 | github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= 6 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 7 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 8 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 9 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 10 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 11 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 12 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 13 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 14 | github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs= 15 | github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= 16 | github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= 17 | github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= 18 | github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= 19 | github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= 20 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 21 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= 22 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 23 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 24 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 25 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 26 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 27 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= 28 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 29 | golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= 30 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 31 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 32 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 33 | golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 34 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 35 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 36 | golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= 37 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 39 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 40 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 41 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 42 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 43 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 44 | -------------------------------------------------------------------------------- /examples/senddnsqueries/senddnsqueries.go: -------------------------------------------------------------------------------- 1 | /* 2 | senddnsqueries pre-generates a frame with a DNS query and starts sending it in 3 | and endless loop to given destination as fast as possible. 4 | */ 5 | package main 6 | 7 | import ( 8 | "encoding/hex" 9 | "flag" 10 | "fmt" 11 | "math" 12 | "net" 13 | "time" 14 | 15 | "github.com/google/gopacket" 16 | "github.com/google/gopacket/layers" 17 | "github.com/miekg/dns" 18 | "github.com/slavc/xdp" 19 | "github.com/vishvananda/netlink" 20 | ) 21 | 22 | // ... 23 | var ( 24 | NIC string 25 | QueueID int 26 | SrcMAC string 27 | DstMAC string 28 | SrcIP string 29 | DstIP string 30 | DomainName string 31 | ) 32 | 33 | func main() { 34 | flag.StringVar(&NIC, "interface", "enp3s0", "Network interface to attach to.") 35 | flag.IntVar(&QueueID, "queue", 0, "The queue on the network interface to attach to.") 36 | flag.StringVar(&SrcMAC, "srcmac", "b2968175b211", "Source MAC address to use in sent frames.") 37 | flag.StringVar(&DstMAC, "dstmac", "ffffffffffff", "Destination MAC address to use in sent frames.") 38 | flag.StringVar(&SrcIP, "srcip", "192.168.111.1", "Source IP address to use in sent frames.") 39 | flag.StringVar(&DstIP, "dstip", "192.168.111.10", "Destination IP address to use in sent frames.") 40 | flag.StringVar(&DomainName, "domain", "google.com", "Domain name to use in the DNS query.") 41 | flag.Parse() 42 | 43 | // Initialize the XDP socket. 44 | 45 | link, err := netlink.LinkByName(NIC) 46 | if err != nil { 47 | panic(err) 48 | } 49 | 50 | xsk, err := xdp.NewSocket(link.Attrs().Index, QueueID, nil) 51 | if err != nil { 52 | panic(err) 53 | } 54 | 55 | // Pre-generate a frame containing a DNS query. 56 | 57 | srcMAC, _ := hex.DecodeString(SrcMAC) 58 | dstMAC, _ := hex.DecodeString(DstMAC) 59 | 60 | eth := &layers.Ethernet{ 61 | SrcMAC: net.HardwareAddr(srcMAC), 62 | DstMAC: net.HardwareAddr(dstMAC), 63 | EthernetType: layers.EthernetTypeIPv4, 64 | } 65 | ip := &layers.IPv4{ 66 | Version: 4, 67 | IHL: 5, 68 | TTL: 64, 69 | Id: 0, 70 | Protocol: layers.IPProtocolUDP, 71 | SrcIP: net.ParseIP(SrcIP).To4(), 72 | DstIP: net.ParseIP(DstIP).To4(), 73 | } 74 | udp := &layers.UDP{ 75 | SrcPort: 1234, 76 | DstPort: 53, 77 | } 78 | udp.SetNetworkLayerForChecksum(ip) 79 | query := new(dns.Msg) 80 | query.SetQuestion(dns.Fqdn(DomainName), dns.TypeA) 81 | payload, err := query.Pack() 82 | if err != nil { 83 | panic(err) 84 | } 85 | 86 | buf := gopacket.NewSerializeBuffer() 87 | opts := gopacket.SerializeOptions{ 88 | FixLengths: true, 89 | ComputeChecksums: true, 90 | } 91 | err = gopacket.SerializeLayers(buf, opts, eth, ip, udp, gopacket.Payload(payload)) 92 | if err != nil { 93 | panic(err) 94 | } 95 | frameLen := len(buf.Bytes()) 96 | 97 | // Fill all the frames in UMEM with the pre-generated DNS query frame. 98 | 99 | descs := xsk.GetDescs(math.MaxInt32, false) 100 | for i := range descs { 101 | frameLen = copy(xsk.GetFrame(descs[i]), buf.Bytes()) 102 | } 103 | 104 | // Start sending the pre-generated frame as quickly as possible in an 105 | // endless loop printing statistics of the number of sent frames and 106 | // the number of sent bytes every second. 107 | 108 | fmt.Printf("sending DNS queries from %v (%v) to %v (%v) for domain name %s...\n", ip.SrcIP, eth.SrcMAC, ip.DstIP, eth.DstMAC, DomainName) 109 | 110 | go func() { 111 | var err error 112 | var prev xdp.Stats 113 | var cur xdp.Stats 114 | var numPkts uint64 115 | for i := uint64(0); ; i++ { 116 | time.Sleep(time.Duration(1) * time.Second) 117 | cur, err = xsk.Stats() 118 | if err != nil { 119 | panic(err) 120 | } 121 | numPkts = cur.Completed - prev.Completed 122 | fmt.Printf("%d packets/s (%d bytes/s)\n", numPkts, numPkts*uint64(frameLen)) 123 | prev = cur 124 | } 125 | }() 126 | 127 | for { 128 | descs := xsk.GetDescs(xsk.NumFreeTxSlots(), false) 129 | for i := range descs { 130 | descs[i].Len = uint32(frameLen) 131 | } 132 | xsk.Transmit(descs) 133 | 134 | _, _, err = xsk.Poll(1) 135 | if err != nil { 136 | panic(err) 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/include/bpf/bpf_endian.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __BPF_ENDIAN__ 3 | #define __BPF_ENDIAN__ 4 | 5 | /* 6 | * Isolate byte #n and put it into byte #m, for __u##b type. 7 | * E.g., moving byte #6 (nnnnnnnn) into byte #1 (mmmmmmmm) for __u64: 8 | * 1) xxxxxxxx nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 9 | * 2) nnnnnnnn xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx mmmmmmmm xxxxxxxx 00000000 10 | * 3) 00000000 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 11 | * 4) 00000000 00000000 00000000 00000000 00000000 00000000 nnnnnnnn 00000000 12 | */ 13 | #define ___bpf_mvb(x, b, n, m) ((__u##b)(x) << (b-(n+1)*8) >> (b-8) << (m*8)) 14 | 15 | #define ___bpf_swab16(x) ((__u16)( \ 16 | ___bpf_mvb(x, 16, 0, 1) | \ 17 | ___bpf_mvb(x, 16, 1, 0))) 18 | 19 | #define ___bpf_swab32(x) ((__u32)( \ 20 | ___bpf_mvb(x, 32, 0, 3) | \ 21 | ___bpf_mvb(x, 32, 1, 2) | \ 22 | ___bpf_mvb(x, 32, 2, 1) | \ 23 | ___bpf_mvb(x, 32, 3, 0))) 24 | 25 | #define ___bpf_swab64(x) ((__u64)( \ 26 | ___bpf_mvb(x, 64, 0, 7) | \ 27 | ___bpf_mvb(x, 64, 1, 6) | \ 28 | ___bpf_mvb(x, 64, 2, 5) | \ 29 | ___bpf_mvb(x, 64, 3, 4) | \ 30 | ___bpf_mvb(x, 64, 4, 3) | \ 31 | ___bpf_mvb(x, 64, 5, 2) | \ 32 | ___bpf_mvb(x, 64, 6, 1) | \ 33 | ___bpf_mvb(x, 64, 7, 0))) 34 | 35 | /* LLVM's BPF target selects the endianness of the CPU 36 | * it compiles on, or the user specifies (bpfel/bpfeb), 37 | * respectively. The used __BYTE_ORDER__ is defined by 38 | * the compiler, we cannot rely on __BYTE_ORDER from 39 | * libc headers, since it doesn't reflect the actual 40 | * requested byte order. 41 | * 42 | * Note, LLVM's BPF target has different __builtin_bswapX() 43 | * semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE 44 | * in bpfel and bpfeb case, which means below, that we map 45 | * to cpu_to_be16(). We could use it unconditionally in BPF 46 | * case, but better not rely on it, so that this header here 47 | * can be used from application and BPF program side, which 48 | * use different targets. 49 | */ 50 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 51 | # define __bpf_ntohs(x) __builtin_bswap16(x) 52 | # define __bpf_htons(x) __builtin_bswap16(x) 53 | # define __bpf_constant_ntohs(x) ___bpf_swab16(x) 54 | # define __bpf_constant_htons(x) ___bpf_swab16(x) 55 | # define __bpf_ntohl(x) __builtin_bswap32(x) 56 | # define __bpf_htonl(x) __builtin_bswap32(x) 57 | # define __bpf_constant_ntohl(x) ___bpf_swab32(x) 58 | # define __bpf_constant_htonl(x) ___bpf_swab32(x) 59 | # define __bpf_be64_to_cpu(x) __builtin_bswap64(x) 60 | # define __bpf_cpu_to_be64(x) __builtin_bswap64(x) 61 | # define __bpf_constant_be64_to_cpu(x) ___bpf_swab64(x) 62 | # define __bpf_constant_cpu_to_be64(x) ___bpf_swab64(x) 63 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 64 | # define __bpf_ntohs(x) (x) 65 | # define __bpf_htons(x) (x) 66 | # define __bpf_constant_ntohs(x) (x) 67 | # define __bpf_constant_htons(x) (x) 68 | # define __bpf_ntohl(x) (x) 69 | # define __bpf_htonl(x) (x) 70 | # define __bpf_constant_ntohl(x) (x) 71 | # define __bpf_constant_htonl(x) (x) 72 | # define __bpf_be64_to_cpu(x) (x) 73 | # define __bpf_cpu_to_be64(x) (x) 74 | # define __bpf_constant_be64_to_cpu(x) (x) 75 | # define __bpf_constant_cpu_to_be64(x) (x) 76 | #else 77 | # error "Fix your compiler's __BYTE_ORDER__?!" 78 | #endif 79 | 80 | #define bpf_htons(x) \ 81 | (__builtin_constant_p(x) ? \ 82 | __bpf_constant_htons(x) : __bpf_htons(x)) 83 | #define bpf_ntohs(x) \ 84 | (__builtin_constant_p(x) ? \ 85 | __bpf_constant_ntohs(x) : __bpf_ntohs(x)) 86 | #define bpf_htonl(x) \ 87 | (__builtin_constant_p(x) ? \ 88 | __bpf_constant_htonl(x) : __bpf_htonl(x)) 89 | #define bpf_ntohl(x) \ 90 | (__builtin_constant_p(x) ? \ 91 | __bpf_constant_ntohl(x) : __bpf_ntohl(x)) 92 | #define bpf_cpu_to_be64(x) \ 93 | (__builtin_constant_p(x) ? \ 94 | __bpf_constant_cpu_to_be64(x) : __bpf_cpu_to_be64(x)) 95 | #define bpf_be64_to_cpu(x) \ 96 | (__builtin_constant_p(x) ? \ 97 | __bpf_constant_be64_to_cpu(x) : __bpf_be64_to_cpu(x)) 98 | 99 | #endif /* __BPF_ENDIAN__ */ 100 | -------------------------------------------------------------------------------- /examples/sendudp/sendudp.go: -------------------------------------------------------------------------------- 1 | /* 2 | sendudp pre-generates a frame with a UDP packet with a payload of the given 3 | size and starts sending it in and endless loop to given destination as fast as 4 | possible. 5 | */ 6 | package main 7 | 8 | import ( 9 | "encoding/hex" 10 | "flag" 11 | "fmt" 12 | "math" 13 | "net" 14 | "time" 15 | 16 | "github.com/slavc/xdp" 17 | "github.com/google/gopacket" 18 | "github.com/google/gopacket/layers" 19 | "github.com/vishvananda/netlink" 20 | ) 21 | 22 | // ... 23 | var ( 24 | NIC string 25 | QueueID int 26 | SrcMAC string 27 | DstMAC string 28 | SrcIP string 29 | DstIP string 30 | SrcPort uint 31 | DstPort uint 32 | PayloadSize uint 33 | ) 34 | 35 | func main() { 36 | flag.StringVar(&NIC, "interface", "ens9", "Network interface to attach to.") 37 | flag.IntVar(&QueueID, "queue", 0, "The queue on the network interface to attach to.") 38 | flag.StringVar(&SrcMAC, "srcmac", "b2968175b211", "Source MAC address to use in sent frames.") 39 | flag.StringVar(&DstMAC, "dstmac", "ffffffffffff", "Destination MAC address to use in sent frames.") 40 | flag.StringVar(&SrcIP, "srcip", "192.168.111.10", "Source IP address to use in sent frames.") 41 | flag.StringVar(&DstIP, "dstip", "192.168.111.1", "Destination IP address to use in sent frames.") 42 | flag.UintVar(&SrcPort, "srcport", 1234, "Source UDP port.") 43 | flag.UintVar(&DstPort, "dstport", 1234, "Destination UDP port.") 44 | flag.UintVar(&PayloadSize, "payloadsize", 1400, "Size of the UDP payload.") 45 | flag.Parse() 46 | 47 | // Initialize the XDP socket. 48 | 49 | link, err := netlink.LinkByName(NIC) 50 | if err != nil { 51 | panic(err) 52 | } 53 | 54 | xsk, err := xdp.NewSocket(link.Attrs().Index, QueueID, nil) 55 | if err != nil { 56 | panic(err) 57 | } 58 | 59 | // Pre-generate a frame containing a DNS query. 60 | 61 | srcMAC, _ := hex.DecodeString(SrcMAC) 62 | dstMAC, _ := hex.DecodeString(DstMAC) 63 | 64 | eth := &layers.Ethernet{ 65 | SrcMAC: net.HardwareAddr(srcMAC), 66 | DstMAC: net.HardwareAddr(dstMAC), 67 | EthernetType: layers.EthernetTypeIPv4, 68 | } 69 | ip := &layers.IPv4{ 70 | Version: 4, 71 | IHL: 5, 72 | TTL: 64, 73 | Id: 0, 74 | Protocol: layers.IPProtocolUDP, 75 | SrcIP: net.ParseIP(SrcIP).To4(), 76 | DstIP: net.ParseIP(DstIP).To4(), 77 | } 78 | udp := &layers.UDP{ 79 | SrcPort: layers.UDPPort(SrcPort), 80 | DstPort: layers.UDPPort(DstPort), 81 | } 82 | udp.SetNetworkLayerForChecksum(ip) 83 | payload := make([]byte, PayloadSize) 84 | for i := 0; i < len(payload); i++ { 85 | payload[i] = byte(i) 86 | } 87 | 88 | buf := gopacket.NewSerializeBuffer() 89 | opts := gopacket.SerializeOptions{ 90 | FixLengths: true, 91 | ComputeChecksums: true, 92 | } 93 | err = gopacket.SerializeLayers(buf, opts, eth, ip, udp, gopacket.Payload(payload)) 94 | if err != nil { 95 | panic(err) 96 | } 97 | frameLen := len(buf.Bytes()) 98 | 99 | // Fill all the frames in UMEM with the pre-generated UDP packet. 100 | 101 | descs := xsk.GetDescs(math.MaxInt32, false) 102 | for i := range descs { 103 | frameLen = copy(xsk.GetFrame(descs[i]), buf.Bytes()) 104 | } 105 | 106 | // Start sending the pre-generated frame as quickly as possible in an 107 | // endless loop printing statistics of the number of sent frames and 108 | // the number of sent bytes every second. 109 | 110 | fmt.Printf("sending UDP packets from %v (%v) to %v (%v)...\n", ip.SrcIP, eth.SrcMAC, ip.DstIP, eth.DstMAC) 111 | 112 | go func() { 113 | var err error 114 | var prev xdp.Stats 115 | var cur xdp.Stats 116 | var numPkts uint64 117 | for i := uint64(0); ; i++ { 118 | time.Sleep(time.Duration(1) * time.Second) 119 | cur, err = xsk.Stats() 120 | if err != nil { 121 | panic(err) 122 | } 123 | numPkts = cur.Completed - prev.Completed 124 | fmt.Printf("%d packets/s (%d Mb/s)\n", numPkts, (numPkts*uint64(frameLen)*8)/(1000*1000)) 125 | prev = cur 126 | } 127 | }() 128 | 129 | for { 130 | descs := xsk.GetDescs(xsk.NumFreeTxSlots(), false) 131 | for i := range descs { 132 | descs[i].Len = uint32(frameLen) 133 | } 134 | xsk.Transmit(descs) 135 | 136 | _, _, err = xsk.Poll(-1) 137 | if err != nil { 138 | panic(err) 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /examples/dumpframes/dumpframes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Asavie Technologies Ltd. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | /* 8 | dumpframes demostrates how to receive frames from a network link using 9 | github.com/slavc/xdp package, it sets up an XDP socket attached to a 10 | particular network link and dumps all frames it receives to standard output. 11 | */ 12 | package main 13 | 14 | import ( 15 | "encoding/hex" 16 | "flag" 17 | "fmt" 18 | "log" 19 | "net" 20 | 21 | "github.com/slavc/xdp" 22 | "github.com/slavc/xdp/examples/dumpframes/ebpf" 23 | "github.com/google/gopacket" 24 | "github.com/google/gopacket/layers" 25 | ) 26 | 27 | func main() { 28 | var linkName string 29 | var queueID int 30 | var protocol int64 31 | 32 | log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds) 33 | 34 | flag.StringVar(&linkName, "linkname", "enp3s0", "The network link on which rebroadcast should run on.") 35 | flag.IntVar(&queueID, "queueid", 0, "The ID of the Rx queue to which to attach to on the network link.") 36 | flag.Int64Var(&protocol, "ip-proto", 0, "If greater than 0 and less than or equal to 255, limit xdp bpf_redirect_map to packets with the specified IP protocol number.") 37 | flag.Parse() 38 | 39 | interfaces, err := net.Interfaces() 40 | if err != nil { 41 | fmt.Printf("error: failed to fetch the list of network interfaces on the system: %v\n", err) 42 | return 43 | } 44 | 45 | Ifindex := -1 46 | for _, iface := range interfaces { 47 | if iface.Name == linkName { 48 | Ifindex = iface.Index 49 | break 50 | } 51 | } 52 | if Ifindex == -1 { 53 | fmt.Printf("error: couldn't find a suitable network interface to attach to\n") 54 | return 55 | } 56 | 57 | var program *xdp.Program 58 | 59 | // Create a new XDP eBPF program and attach it to our chosen network link. 60 | if protocol == 0 { 61 | program, err = xdp.NewProgram(queueID + 1) 62 | } else { 63 | program, err = ebpf.NewIPProtoProgram(uint32(protocol), nil) 64 | } 65 | if err != nil { 66 | fmt.Printf("error: failed to create xdp program: %v\n", err) 67 | return 68 | } 69 | defer program.Close() 70 | if err := program.Attach(Ifindex); err != nil { 71 | fmt.Printf("error: failed to attach xdp program to interface: %v\n", err) 72 | return 73 | } 74 | defer program.Detach(Ifindex) 75 | 76 | // Create and initialize an XDP socket attached to our chosen network 77 | // link. 78 | xsk, err := xdp.NewSocket(Ifindex, queueID, nil) 79 | if err != nil { 80 | fmt.Printf("error: failed to create an XDP socket: %v\n", err) 81 | return 82 | } 83 | 84 | // Register our XDP socket file descriptor with the eBPF program so it can be redirected packets 85 | if err := program.Register(queueID, xsk.FD()); err != nil { 86 | fmt.Printf("error: failed to register socket in BPF map: %v\n", err) 87 | return 88 | } 89 | defer program.Unregister(queueID) 90 | 91 | for { 92 | // If there are any free slots on the Fill queue... 93 | if n := xsk.NumFreeFillSlots(); n > 0 { 94 | // ...then fetch up to that number of not-in-use 95 | // descriptors and push them onto the Fill ring queue 96 | // for the kernel to fill them with the received 97 | // frames. 98 | xsk.Fill(xsk.GetDescs(n, true)) 99 | } 100 | 101 | // Wait for receive - meaning the kernel has 102 | // produced one or more descriptors filled with a received 103 | // frame onto the Rx ring queue. 104 | log.Printf("waiting for frame(s) to be received...") 105 | numRx, _, err := xsk.Poll(-1) 106 | if err != nil { 107 | fmt.Printf("error: %v\n", err) 108 | return 109 | } 110 | 111 | if numRx > 0 { 112 | // Consume the descriptors filled with received frames 113 | // from the Rx ring queue. 114 | rxDescs := xsk.Receive(numRx) 115 | 116 | // Print the received frames and also modify them 117 | // in-place replacing the destination MAC address with 118 | // broadcast address. 119 | for i := 0; i < len(rxDescs); i++ { 120 | pktData := xsk.GetFrame(rxDescs[i]) 121 | pkt := gopacket.NewPacket(pktData, layers.LayerTypeEthernet, gopacket.Default) 122 | log.Printf("received frame:\n%s%+v", hex.Dump(pktData[:]), pkt) 123 | } 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /examples/rebroadcast/rebroadcast.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Asavie Technologies Ltd. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | /* 8 | rebroadcast demonstrates how to receive and transmit network frames using 9 | the github.com/slavc/xdp package, it receives frames on the given network 10 | interface using an XDP socket, prints the received frames to stdout, 11 | modifies their the destination MAC address to the broadcast address of 12 | ff:ff:ff:ff:ff:ff in-line and sends the frames back out the same network 13 | interface. 14 | */ 15 | package main 16 | 17 | import ( 18 | "encoding/hex" 19 | "flag" 20 | "fmt" 21 | "net" 22 | 23 | "github.com/slavc/xdp" 24 | "github.com/google/gopacket" 25 | "github.com/google/gopacket/layers" 26 | ) 27 | 28 | func main() { 29 | var linkName string 30 | var queueID int 31 | 32 | flag.StringVar(&linkName, "linkname", "enp3s0", "The network link on which rebroadcast should run on.") 33 | flag.IntVar(&queueID, "queueid", 0, "The ID of the Rx queue to which to attach to on the network link.") 34 | flag.Parse() 35 | 36 | interfaces, err := net.Interfaces() 37 | if err != nil { 38 | fmt.Printf("error: failed to fetch the list of network interfaces on the system: %v\n", err) 39 | return 40 | } 41 | 42 | Ifindex := -1 43 | for _, iface := range interfaces { 44 | if iface.Name == linkName { 45 | Ifindex = iface.Index 46 | break 47 | } 48 | } 49 | if Ifindex == -1 { 50 | fmt.Printf("error: couldn't find a suitable network interface to attach to\n") 51 | return 52 | } 53 | 54 | // Create a new XDP eBPF program and attach it to our chosen network link. 55 | program, err := xdp.NewProgram(queueID + 1) 56 | if err != nil { 57 | fmt.Printf("error: failed to create xdp program: %v\n", err) 58 | return 59 | } 60 | defer program.Close() 61 | if err := program.Attach(Ifindex); err != nil { 62 | fmt.Printf("error: failed to attach xdp program to interface: %v\n", err) 63 | return 64 | } 65 | defer program.Detach(Ifindex) 66 | 67 | // Create and initialize an XDP socket attached to our chosen network 68 | // link. 69 | xsk, err := xdp.NewSocket(Ifindex, queueID, nil) 70 | if err != nil { 71 | fmt.Printf("error: failed to create an XDP socket: %v\n", err) 72 | return 73 | } 74 | 75 | // Register our XDP socket file descriptor with the eBPF program so it can be redirected packets 76 | if err := program.Register(queueID, xsk.FD()); err != nil { 77 | fmt.Printf("error: failed to register socket in BPF map: %v\n", err) 78 | return 79 | } 80 | defer program.Unregister(queueID) 81 | 82 | for numPkts := 0; ; numPkts++ { 83 | fmt.Printf(">>> ITERATION %d <<<\n", numPkts) 84 | 85 | // If there are any free slots on the Fill queue... 86 | if n := xsk.NumFreeFillSlots(); n > 0 { 87 | // ...then fetch up to that number of not-in-use 88 | // descriptors and push them onto the Fill ring queue 89 | // for the kernel to fill them with the received 90 | // frames. 91 | xsk.Fill(xsk.GetDescs(n, true)) 92 | } 93 | fmt.Printf(" fill=%d, rx=%d, tx=%d, complete=%d\n", xsk.NumFilled(), xsk.NumReceived(), xsk.NumTransmitted(), xsk.NumCompleted()) 94 | 95 | // Wait for events: either receive - meaning the kernel has 96 | // produced one or more descriptors filled with a received 97 | // frame onto the Rx ring queue; or completion - meaning the 98 | // kernel finished sending one or more frames, previously 99 | // produced by us onto Tx ring queue, and has produced onto the 100 | // Completion ring queue. 101 | // Both events mean that some descriptors are not-in-use any 102 | // more and can be recycled. 103 | fmt.Printf("waiting for events...\n") 104 | numRx, numCompl, err := xsk.Poll(-1) 105 | if err != nil { 106 | fmt.Printf("error: %v\n", err) 107 | return 108 | } 109 | fmt.Printf(" fill=%d, rx=%d, tx=%d, complete=%d\n", xsk.NumFilled(), xsk.NumReceived(), xsk.NumTransmitted(), xsk.NumCompleted()) 110 | fmt.Printf("received: %d\ncompleted: %d\n", numRx, numCompl) 111 | 112 | if numRx > 0 { 113 | // Consume the descriptors filled with received frames 114 | // from the Rx ring queue. 115 | rxDescs := xsk.Receive(numRx) 116 | 117 | // Print the received frames and also modify them 118 | // in-place replacing the destination MAC address with 119 | // broadcast address. 120 | for i := 0; i < len(rxDescs); i++ { 121 | pktData := xsk.GetFrame(rxDescs[i]) 122 | pkt := gopacket.NewPacket(pktData, layers.LayerTypeEthernet, gopacket.Default) 123 | fmt.Printf("received frame %d:\nhexdump:\n%s\n\n%+v\n\n", i, hex.Dump(pktData[:]), pkt) 124 | 125 | // Set destination MAC address to 126 | // ff:ff:ff:ff:ff:ff, i.e. the broadcast 127 | // address. 128 | for i := 0; i < 6; i++ { 129 | pktData[i] = byte(0xff) 130 | } 131 | } 132 | 133 | // Send the modified frames back out. 134 | n := xsk.Transmit(rxDescs) 135 | fmt.Printf("sent: %d\n", n) 136 | fmt.Printf(" fill=%d, rx=%d, tx=%d, complete=%d\n", xsk.NumFilled(), xsk.NumReceived(), xsk.NumTransmitted(), xsk.NumCompleted()) 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /examples/l2fwd/l2fwd.go: -------------------------------------------------------------------------------- 1 | /* 2 | l2fwd is a primitive layer 2 frame forwarder, it attaches to two given network 3 | links and transmits any frames received on any of them on the other network 4 | link with the given destination MAC address. 5 | */ 6 | package main 7 | 8 | import ( 9 | "flag" 10 | "fmt" 11 | "log" 12 | "net" 13 | "os" 14 | "syscall" 15 | "time" 16 | 17 | "github.com/slavc/xdp" 18 | "github.com/vishvananda/netlink" 19 | "golang.org/x/sys/unix" 20 | ) 21 | 22 | func main() { 23 | var inLinkName string 24 | var inLinkDstStr string 25 | var inLinkQueueID int 26 | var outLinkName string 27 | var outLinkDstStr string 28 | var outLinkQueueID int 29 | var verbose bool 30 | 31 | flag.Usage = func() { 32 | fmt.Fprintf(flag.CommandLine.Output(), "usage: %s -inlink -outlink \n", os.Args[0]) 33 | flag.PrintDefaults() 34 | } 35 | flag.StringVar(&inLinkName, "inlink", "", "Input network link name.") 36 | flag.IntVar(&inLinkQueueID, "inlinkqueue", 0, "The queue ID to attach to on input link.") 37 | flag.StringVar(&inLinkDstStr, "inlinkdst", "ff:ff:ff:ff:ff:ff", "Destination MAC address to forward frames to from 'in' interface.") 38 | flag.StringVar(&outLinkName, "outlink", "", "Output network link name.") 39 | flag.IntVar(&outLinkQueueID, "outlinkqueue", 0, "The queue ID to attach to on output link.") 40 | flag.StringVar(&outLinkDstStr, "outlinkdst", "ff:ff:ff:ff:ff:ff", "Destination MAC address to forward frames to from 'out' interface.") 41 | flag.BoolVar(&verbose, "verbose", false, "Output forwarding statistics.") 42 | flag.Parse() 43 | 44 | if inLinkName == "" || outLinkName == "" { 45 | flag.Usage() 46 | os.Exit(1) 47 | } 48 | 49 | inLinkDst, err := net.ParseMAC(inLinkDstStr) 50 | if err != nil { 51 | flag.Usage() 52 | os.Exit(1) 53 | } 54 | 55 | outLinkDst, err := net.ParseMAC(outLinkDstStr) 56 | if err != nil { 57 | flag.Usage() 58 | os.Exit(1) 59 | } 60 | 61 | inLink, err := netlink.LinkByName(inLinkName) 62 | if err != nil { 63 | log.Fatalf("failed to fetch info about link %s: %v", inLinkName, err) 64 | } 65 | 66 | outLink, err := netlink.LinkByName(outLinkName) 67 | if err != nil { 68 | log.Fatalf("failed to fetch info about link %s: %v", outLinkName, err) 69 | } 70 | 71 | forwardL2(verbose, inLink, inLinkQueueID, inLinkDst, outLink, outLinkQueueID, outLinkDst) 72 | } 73 | 74 | func forwardL2(verbose bool, inLink netlink.Link, inLinkQueueID int, inLinkDst net.HardwareAddr, outLink netlink.Link, outLinkQueueID int, outLinkDst net.HardwareAddr) { 75 | log.Printf("attaching XDP program for %s...", inLink.Attrs().Name) 76 | inProg, err := xdp.NewProgram(inLinkQueueID + 1) 77 | if err != nil { 78 | log.Fatalf("failed to create xdp program: %v\n", err) 79 | } 80 | if err := inProg.Attach(inLink.Attrs().Index); err != nil { 81 | log.Fatalf("failed to attach xdp program to interface: %v\n", err) 82 | } 83 | defer inProg.Detach(inLink.Attrs().Index) 84 | log.Printf("opening XDP socket for %s...", inLink.Attrs().Name) 85 | inXsk, err := xdp.NewSocket(inLink.Attrs().Index, inLinkQueueID, nil) 86 | if err != nil { 87 | log.Fatalf("failed to open XDP socket for link %s: %v", inLink.Attrs().Name, err) 88 | } 89 | log.Printf("registering XDP socket for %s...", inLink.Attrs().Name) 90 | if err := inProg.Register(inLinkQueueID, inXsk.FD()); err != nil { 91 | fmt.Printf("error: failed to register socket in BPF map: %v\n", err) 92 | return 93 | } 94 | defer inProg.Unregister(inLinkQueueID) 95 | 96 | // Note: The XDP socket used for transmitting data does not need an EBPF program. 97 | log.Printf("opening XDP socket for %s...", outLink.Attrs().Name) 98 | outXsk, err := xdp.NewSocket(outLink.Attrs().Index, outLinkQueueID, nil) 99 | if err != nil { 100 | log.Fatalf("failed to open XDP socket for link %s: %v", outLink.Attrs().Name, err) 101 | } 102 | 103 | log.Printf("starting L2 forwarder...") 104 | 105 | numBytesTotal := uint64(0) 106 | numFramesTotal := uint64(0) 107 | if verbose { 108 | go func() { 109 | var numBytesPrev, numFramesPrev uint64 110 | var numBytesNow, numFramesNow uint64 111 | for { 112 | numBytesPrev = numBytesNow 113 | numFramesPrev = numFramesNow 114 | time.Sleep(time.Duration(1) * time.Second) 115 | numBytesNow = numBytesTotal 116 | numFramesNow = numFramesTotal 117 | pps := numFramesNow - numFramesPrev 118 | bps := (numBytesNow - numBytesPrev) * 8 119 | log.Printf("%9d pps / %6d Mbps", pps, bps/1000000) 120 | } 121 | }() 122 | } 123 | 124 | var fds [2]unix.PollFd 125 | fds[0].Fd = int32(inXsk.FD()) 126 | fds[1].Fd = int32(outXsk.FD()) 127 | for { 128 | inXsk.Fill(inXsk.GetDescs(inXsk.NumFreeFillSlots(), true)) 129 | outXsk.Fill(outXsk.GetDescs(outXsk.NumFreeFillSlots(), true)) 130 | 131 | fds[0].Events = unix.POLLIN 132 | if inXsk.NumTransmitted() > 0 { 133 | fds[0].Events |= unix.POLLOUT 134 | } 135 | 136 | fds[1].Events = unix.POLLIN 137 | if outXsk.NumTransmitted() > 0 { 138 | fds[1].Events |= unix.POLLOUT 139 | } 140 | 141 | fds[0].Revents = 0 142 | fds[1].Revents = 0 143 | _, err := unix.Poll(fds[:], -1) 144 | if err == syscall.EINTR { 145 | // EINTR is a non-fatal error that may occur due to ongoing syscalls that interrupt our poll 146 | continue 147 | } else if err != nil { 148 | fmt.Fprintf(os.Stderr, "poll failed: %v\n", err) 149 | os.Exit(1) 150 | } 151 | 152 | if (fds[0].Revents & unix.POLLIN) != 0 { 153 | numBytes, numFrames := forwardFrames(inXsk, outXsk, inLinkDst) 154 | numBytesTotal += numBytes 155 | numFramesTotal += numFrames 156 | } 157 | if (fds[0].Revents & unix.POLLOUT) != 0 { 158 | inXsk.Complete(inXsk.NumCompleted()) 159 | } 160 | if (fds[1].Revents & unix.POLLIN) != 0 { 161 | numBytes, numFrames := forwardFrames(outXsk, inXsk, outLinkDst) 162 | numBytesTotal += numBytes 163 | numFramesTotal += numFrames 164 | } 165 | if (fds[1].Revents & unix.POLLOUT) != 0 { 166 | outXsk.Complete(outXsk.NumCompleted()) 167 | } 168 | } 169 | } 170 | 171 | func forwardFrames(input *xdp.Socket, output *xdp.Socket, dstMac net.HardwareAddr) (numBytes uint64, numFrames uint64) { 172 | inDescs := input.Receive(input.NumReceived()) 173 | replaceDstMac(input, inDescs, dstMac) 174 | 175 | outDescs := output.GetDescs(output.NumFreeTxSlots(), false) 176 | 177 | if len(inDescs) > len(outDescs) { 178 | inDescs = inDescs[:len(outDescs)] 179 | } 180 | numFrames = uint64(len(inDescs)) 181 | 182 | for i := 0; i < len(inDescs); i++ { 183 | outFrame := output.GetFrame(outDescs[i]) 184 | inFrame := input.GetFrame(inDescs[i]) 185 | numBytes += uint64(len(inFrame)) 186 | outDescs[i].Len = uint32(copy(outFrame, inFrame)) 187 | } 188 | outDescs = outDescs[:len(inDescs)] 189 | 190 | output.Transmit(outDescs) 191 | 192 | return 193 | } 194 | 195 | func replaceDstMac(xsk *xdp.Socket, descs []xdp.Desc, dstMac net.HardwareAddr) { 196 | for _, d := range descs { 197 | frame := xsk.GetFrame(d) 198 | copy(frame, dstMac) 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /program.go: -------------------------------------------------------------------------------- 1 | package xdp 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | "unsafe" 7 | 8 | "github.com/cilium/ebpf" 9 | "github.com/cilium/ebpf/asm" 10 | "github.com/vishvananda/netlink" 11 | ) 12 | 13 | // Program represents the necessary data structures for a simple XDP program that can filter traffic 14 | // based on the attached rx queue. 15 | type Program struct { 16 | Program *ebpf.Program 17 | Queues *ebpf.Map 18 | Sockets *ebpf.Map 19 | } 20 | 21 | // Attach the XDP Program to an interface. 22 | func (p *Program) Attach(Ifindex int) error { 23 | if err := removeProgram(Ifindex); err != nil { 24 | return err 25 | } 26 | return attachProgram(Ifindex, p.Program) 27 | } 28 | 29 | // Detach the XDP Program from an interface. 30 | func (p *Program) Detach(Ifindex int) error { 31 | return removeProgram(Ifindex) 32 | } 33 | 34 | // Register adds the socket file descriptor as the recipient for packets from the given queueID. 35 | func (p *Program) Register(queueID int, fd int) error { 36 | if err := p.Sockets.Put(uint32(queueID), uint32(fd)); err != nil { 37 | return fmt.Errorf("failed to update xsksMap: %v", err) 38 | } 39 | 40 | if err := p.Queues.Put(uint32(queueID), uint32(1)); err != nil { 41 | return fmt.Errorf("failed to update qidconfMap: %v", err) 42 | } 43 | return nil 44 | } 45 | 46 | // Unregister removes any associated mapping to sockets for the given queueID. 47 | func (p *Program) Unregister(queueID int) error { 48 | if err := p.Queues.Delete(uint32(queueID)); err != nil { 49 | return err 50 | } 51 | if err := p.Sockets.Delete(uint32(queueID)); err != nil { 52 | return err 53 | } 54 | return nil 55 | } 56 | 57 | // Close closes and frees the resources allocated for the Program. 58 | func (p *Program) Close() error { 59 | allErrors := []error{} 60 | if p.Sockets != nil { 61 | if err := p.Sockets.Close(); err != nil { 62 | allErrors = append(allErrors, fmt.Errorf("failed to close xsksMap: %v", err)) 63 | } 64 | p.Sockets = nil 65 | } 66 | 67 | if p.Queues != nil { 68 | if err := p.Queues.Close(); err != nil { 69 | allErrors = append(allErrors, fmt.Errorf("failed to close qidconfMap: %v", err)) 70 | } 71 | p.Queues = nil 72 | } 73 | 74 | if p.Program != nil { 75 | if err := p.Program.Close(); err != nil { 76 | allErrors = append(allErrors, fmt.Errorf("failed to close XDP program: %v", err)) 77 | } 78 | p.Program = nil 79 | } 80 | 81 | if len(allErrors) > 0 { 82 | return allErrors[0] 83 | } 84 | return nil 85 | } 86 | 87 | // NewProgram returns a translation of the default eBPF XDP program found in the 88 | // xsk_load_xdp_prog() function in /tools/lib/bpf/xsk.c: 89 | // https://github.com/torvalds/linux/blob/master/tools/lib/bpf/xsk.c#L259 90 | func NewProgram(maxQueueEntries int) (*Program, error) { 91 | qidconfMap, err := ebpf.NewMap(&ebpf.MapSpec{ 92 | Name: "qidconf_map", 93 | Type: ebpf.Array, 94 | KeySize: uint32(unsafe.Sizeof(int32(0))), 95 | ValueSize: uint32(unsafe.Sizeof(int32(0))), 96 | MaxEntries: uint32(maxQueueEntries), 97 | Flags: 0, 98 | InnerMap: nil, 99 | }) 100 | if err != nil { 101 | return nil, fmt.Errorf("ebpf.NewMap qidconf_map failed (try increasing RLIMIT_MEMLOCK): %v", err) 102 | } 103 | 104 | xsksMap, err := ebpf.NewMap(&ebpf.MapSpec{ 105 | Name: "xsks_map", 106 | Type: ebpf.XSKMap, 107 | KeySize: uint32(unsafe.Sizeof(int32(0))), 108 | ValueSize: uint32(unsafe.Sizeof(int32(0))), 109 | MaxEntries: uint32(maxQueueEntries), 110 | Flags: 0, 111 | InnerMap: nil, 112 | }) 113 | if err != nil { 114 | return nil, fmt.Errorf("ebpf.NewMap xsks_map failed (try increasing RLIMIT_MEMLOCK): %v", err) 115 | } 116 | 117 | /* 118 | This is a translation of the default eBPF XDP program found in the 119 | xsk_load_xdp_prog() function in /tools/lib/bpf/xsk.c: 120 | https://github.com/torvalds/linux/blob/master/tools/lib/bpf/xsk.c#L259 121 | 122 | // This is the C-program: 123 | // SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx) 124 | // { 125 | // int *qidconf, index = ctx->rx_queue_index; 126 | // 127 | // // A set entry here means that the correspnding queue_id 128 | // // has an active AF_XDP socket bound to it. 129 | // qidconf = bpf_map_lookup_elem(&qidconf_map, &index); 130 | // if (!qidconf) 131 | // return XDP_ABORTED; 132 | // 133 | // if (*qidconf) 134 | // return bpf_redirect_map(&xsks_map, index, 0); 135 | // 136 | // return XDP_PASS; 137 | // } 138 | // 139 | struct bpf_insn prog[] = { 140 | // r1 = *(u32 *)(r1 + 16) 141 | BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 16), // 0 142 | // *(u32 *)(r10 - 4) = r1 143 | BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_1, -4), // 1 144 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), // 2 145 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), // 3 146 | BPF_LD_MAP_FD(BPF_REG_1, xsk->qidconf_map_fd), // 4 (2 instructions) 147 | BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), // 5 148 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), // 6 149 | BPF_MOV32_IMM(BPF_REG_0, 0), // 7 150 | // if r1 == 0 goto +8 151 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 8), // 8 152 | BPF_MOV32_IMM(BPF_REG_0, 2), // 9 153 | // r1 = *(u32 *)(r1 + 0) 154 | BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_1, 0), // 10 155 | // if r1 == 0 goto +5 156 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 5), // 11 157 | // r2 = *(u32 *)(r10 - 4) 158 | BPF_LD_MAP_FD(BPF_REG_1, xsk->xsks_map_fd), // 12 (2 instructions) 159 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_10, -4), // 13 160 | BPF_MOV32_IMM(BPF_REG_3, 0), // 14 161 | BPF_EMIT_CALL(BPF_FUNC_redirect_map), // 15 162 | // The jumps are to this instruction 163 | BPF_EXIT_INSN(), // 16 164 | }; 165 | 166 | eBPF instructions: 167 | 0: code: 97 dst_reg: 1 src_reg: 1 off: 16 imm: 0 // 0 168 | 1: code: 99 dst_reg: 10 src_reg: 1 off: -4 imm: 0 // 1 169 | 2: code: 191 dst_reg: 2 src_reg: 10 off: 0 imm: 0 // 2 170 | 3: code: 7 dst_reg: 2 src_reg: 0 off: 0 imm: -4 // 3 171 | 4: code: 24 dst_reg: 1 src_reg: 1 off: 0 imm: 4 // 4 XXX use qidconfMap.FD as IMM 172 | 5: code: 0 dst_reg: 0 src_reg: 0 off: 0 imm: 0 // part of the same instruction 173 | 6: code: 133 dst_reg: 0 src_reg: 0 off: 0 imm: 1 // 5 174 | 7: code: 191 dst_reg: 1 src_reg: 0 off: 0 imm: 0 // 6 175 | 8: code: 180 dst_reg: 0 src_reg: 0 off: 0 imm: 0 // 7 176 | 9: code: 21 dst_reg: 1 src_reg: 0 off: 8 imm: 0 // 8 177 | 10: code: 180 dst_reg: 0 src_reg: 0 off: 0 imm: 2 // 9 178 | 11: code: 97 dst_reg: 1 src_reg: 1 off: 0 imm: 0 // 10 179 | 12: code: 21 dst_reg: 1 src_reg: 0 off: 5 imm: 0 // 11 180 | 13: code: 24 dst_reg: 1 src_reg: 1 off: 0 imm: 5 // 12 XXX use xsksMap.FD as IMM 181 | 14: code: 0 dst_reg: 0 src_reg: 0 off: 0 imm: 0 // part of the same instruction 182 | 15: code: 97 dst_reg: 2 src_reg: 10 off: -4 imm: 0 // 13 183 | 16: code: 180 dst_reg: 3 src_reg: 0 off: 0 imm: 0 // 14 184 | 17: code: 133 dst_reg: 0 src_reg: 0 off: 0 imm: 51 // 15 185 | 18: code: 149 dst_reg: 0 src_reg: 0 off: 0 imm: 0 // 16 186 | */ 187 | 188 | program, err := ebpf.NewProgram(&ebpf.ProgramSpec{ 189 | Name: "xsk_ebpf", 190 | Type: ebpf.XDP, 191 | Instructions: asm.Instructions{ 192 | {OpCode: 97, Dst: 1, Src: 1, Offset: 16}, // 0: code: 97 dst_reg: 1 src_reg: 1 off: 16 imm: 0 // 0 193 | {OpCode: 99, Dst: 10, Src: 1, Offset: -4}, // 1: code: 99 dst_reg: 10 src_reg: 1 off: -4 imm: 0 // 1 194 | {OpCode: 191, Dst: 2, Src: 10}, // 2: code: 191 dst_reg: 2 src_reg: 10 off: 0 imm: 0 // 2 195 | {OpCode: 7, Dst: 2, Src: 0, Offset: 0, Constant: -4}, // 3: code: 7 dst_reg: 2 src_reg: 0 off: 0 imm: -4 // 3 196 | {OpCode: 24, Dst: 1, Src: 1, Offset: 0, Constant: int64(qidconfMap.FD())}, // 4: code: 24 dst_reg: 1 src_reg: 1 off: 0 imm: 4 // 4 XXX use qidconfMap.FD as IMM 197 | //{ OpCode: 0 }, // 5: code: 0 dst_reg: 0 src_reg: 0 off: 0 imm: 0 // part of the same instruction 198 | {OpCode: 133, Dst: 0, Src: 0, Constant: 1}, // 6: code: 133 dst_reg: 0 src_reg: 0 off: 0 imm: 1 // 5 199 | {OpCode: 191, Dst: 1, Src: 0}, // 7: code: 191 dst_reg: 1 src_reg: 0 off: 0 imm: 0 // 6 200 | {OpCode: 180, Dst: 0, Src: 0}, // 8: code: 180 dst_reg: 0 src_reg: 0 off: 0 imm: 0 // 7 201 | {OpCode: 21, Dst: 1, Src: 0, Offset: 8}, // 9: code: 21 dst_reg: 1 src_reg: 0 off: 8 imm: 0 // 8 202 | {OpCode: 180, Dst: 0, Src: 0, Constant: 2}, // 10: code: 180 dst_reg: 0 src_reg: 0 off: 0 imm: 2 // 9 203 | {OpCode: 97, Dst: 1, Src: 1}, // 11: code: 97 dst_reg: 1 src_reg: 1 off: 0 imm: 0 // 10 204 | {OpCode: 21, Dst: 1, Offset: 5}, // 12: code: 21 dst_reg: 1 src_reg: 0 off: 5 imm: 0 // 11 205 | {OpCode: 24, Dst: 1, Src: 1, Constant: int64(xsksMap.FD())}, // 13: code: 24 dst_reg: 1 src_reg: 1 off: 0 imm: 5 // 12 XXX use xsksMap.FD as IMM 206 | //{ OpCode: 0 }, // 14: code: 0 dst_reg: 0 src_reg: 0 off: 0 imm: 0 // part of the same instruction 207 | {OpCode: 97, Dst: 2, Src: 10, Offset: -4}, // 15: code: 97 dst_reg: 2 src_reg: 10 off: -4 imm: 0 // 13 208 | {OpCode: 180, Dst: 3}, // 16: code: 180 dst_reg: 3 src_reg: 0 off: 0 imm: 0 // 14 209 | {OpCode: 133, Constant: 51}, // 17: code: 133 dst_reg: 0 src_reg: 0 off: 0 imm: 51 // 15 210 | {OpCode: 149}, // 18: code: 149 dst_reg: 0 src_reg: 0 off: 0 imm: 0 // 16 211 | }, 212 | License: "LGPL-2.1 or BSD-2-Clause", 213 | KernelVersion: 0, 214 | }) 215 | if err != nil { 216 | return nil, fmt.Errorf("error: ebpf.NewProgram failed: %v", err) 217 | } 218 | 219 | return &Program{Program: program, Queues: qidconfMap, Sockets: xsksMap}, nil 220 | } 221 | 222 | // LoadProgram load a external XDP program, along with queue and socket map; 223 | // fname is the BPF kernel program file (.o); 224 | // funcname is the function name in the program file; 225 | // qidmapname is the Queues map name; 226 | // xskmapname is the Sockets map name; 227 | func LoadProgram(fname, funcname, qidmapname, xskmapname string) (*Program, error) { 228 | prog := new(Program) 229 | col, err := ebpf.LoadCollection(fname) 230 | if err != nil { 231 | return nil, err 232 | } 233 | var ok bool 234 | if prog.Program, ok = col.Programs[funcname]; !ok { 235 | return nil, fmt.Errorf("%v doesn't contain a function named %v", fname, funcname) 236 | } 237 | if prog.Queues, ok = col.Maps[qidmapname]; !ok { 238 | return nil, fmt.Errorf("%v doesn't contain a queue map named %v", fname, qidmapname) 239 | } 240 | if prog.Sockets, ok = col.Maps[xskmapname]; !ok { 241 | return nil, fmt.Errorf("%v doesn't contain a socket map named %v", fname, xskmapname) 242 | } 243 | return prog, nil 244 | } 245 | 246 | // removeProgram removes an existing XDP program from the given network interface. 247 | func removeProgram(Ifindex int) error { 248 | var link netlink.Link 249 | var err error 250 | link, err = netlink.LinkByIndex(Ifindex) 251 | if err != nil { 252 | return err 253 | } 254 | if !isXdpAttached(link) { 255 | return nil 256 | } 257 | if err = netlink.LinkSetXdpFd(link, -1); err != nil { 258 | return fmt.Errorf("netlink.LinkSetXdpFd(link, -1) failed: %v", err) 259 | } 260 | for { 261 | link, err = netlink.LinkByIndex(Ifindex) 262 | if err != nil { 263 | return err 264 | } 265 | if !isXdpAttached(link) { 266 | break 267 | } 268 | time.Sleep(time.Second) 269 | } 270 | return nil 271 | } 272 | 273 | func isXdpAttached(link netlink.Link) bool { 274 | if link.Attrs() != nil && link.Attrs().Xdp != nil && link.Attrs().Xdp.Attached { 275 | return true 276 | } 277 | return false 278 | } 279 | 280 | // attachProgram attaches the given XDP program to the network interface. 281 | func attachProgram(Ifindex int, program *ebpf.Program) error { 282 | link, err := netlink.LinkByIndex(Ifindex) 283 | if err != nil { 284 | return err 285 | } 286 | return netlink.LinkSetXdpFdWithFlags(link, program.FD(), int(DefaultXdpFlags)) 287 | } 288 | -------------------------------------------------------------------------------- /xdp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Asavie Technologies Ltd. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | /* 8 | Package xdp allows to use XDP sockets from Go. 9 | 10 | An XDP socket allows to get packets from a network interface driver into 11 | a userspace process very fast, bypassing the Linux kernel's network 12 | stack, see https://lwn.net/Articles/750845/ for more information. 13 | 14 | NOTE: 15 | 16 | * If your network link device supports multiple queues - you might 17 | not see all of the incoming traffic because it might be e.g. load-balanced 18 | between multiple queues. You can use the `ethtool -L` command to control the 19 | load-balancing behaviour or even make it so that all of the incoming traffic 20 | is put on a single queue. 21 | 22 | * On recent versions of Linux kernel, the eBPF map memory counts towards the 23 | "locked memory" user limit, so most likely you'll have to increase it. On 24 | Fedora Linux, this can be done by running `ulimit -l ` command, or 25 | to make it permanent, by creating a file at 26 | `/etc/security/limits.d/50-lockedmem.conf` with e.g. the following contents 27 | (1MiB should be enough for this package): 28 | * - lockedmem 1048576 29 | logging out and logging back in. 30 | When you hit this limit, you'll get an error that looks like this: 31 | error: failed to create an XDP socket: ebpf.NewMap qidconf_map failed: map create: operation not permitted 32 | 33 | Here is a minimal example of a program which receives network frames, 34 | modifies their destination MAC address in-place to broadcast address and 35 | transmits them back out the same network link: 36 | 37 | package main 38 | 39 | import ( 40 | "os" 41 | "os/signal" 42 | "syscall" 43 | 44 | "github.com/slavc/xdp" 45 | "github.com/vishvananda/netlink" 46 | ) 47 | 48 | func main() { 49 | const LinkName = "enp6s0" 50 | const QueueID = 0 51 | 52 | link, err := netlink.LinkByName(LinkName) 53 | if err != nil { 54 | panic(err) 55 | } 56 | 57 | program, err := xdp.NewProgram(QueueID + 1) 58 | if err != nil { 59 | panic(err) 60 | } 61 | if err := program.Attach(link.Attrs().Index); err != nil { 62 | panic(err) 63 | } 64 | 65 | xsk, err := xdp.NewSocket(link.Attrs().Index, QueueID, nil) 66 | if err != nil { 67 | panic(err) 68 | } 69 | 70 | if err := program.Register(QueueID, xsk.FD()); err != nil { 71 | panic(err) 72 | } 73 | 74 | // Remove the XDP BPF program on interrupt. 75 | c := make(chan os.Signal) 76 | signal.Notify(c, os.Interrupt, syscall.SIGTERM) 77 | go func() { 78 | <-c 79 | program.Detach(link.Attrs().Index) 80 | os.Exit(1) 81 | }() 82 | 83 | for { 84 | xsk.Fill(xsk.GetDescs(xsk.NumFreeFillSlots(), true)) 85 | numRx, _, err := xsk.Poll(-1) 86 | if err != nil { 87 | panic(err) 88 | } 89 | rxDescs := xsk.Receive(numRx) 90 | for i := 0; i < len(rxDescs); i++ { 91 | // Set destination MAC address to 92 | // ff:ff:ff:ff:ff:ff 93 | frame := xsk.GetFrame(rxDescs[i]) 94 | for i := 0; i < 6; i++ { 95 | frame[i] = byte(0xff) 96 | } 97 | } 98 | xsk.Transmit(rxDescs) 99 | } 100 | } 101 | */ 102 | package xdp 103 | 104 | import ( 105 | "fmt" 106 | "reflect" 107 | "syscall" 108 | "unsafe" 109 | 110 | "github.com/cilium/ebpf" 111 | "golang.org/x/sys/unix" 112 | ) 113 | 114 | // DefaultSocketOptions is the default SocketOptions used by an xdp.Socket created without specifying options. 115 | var DefaultSocketOptions = SocketOptions{ 116 | NumFrames: 128, 117 | FrameSize: 2048, 118 | FillRingNumDescs: 64, 119 | CompletionRingNumDescs: 64, 120 | RxRingNumDescs: 64, 121 | TxRingNumDescs: 64, 122 | } 123 | 124 | type umemRing struct { 125 | Producer *uint32 126 | Consumer *uint32 127 | Descs []uint64 128 | } 129 | 130 | type rxTxRing struct { 131 | Producer *uint32 132 | Consumer *uint32 133 | Descs []Desc 134 | } 135 | 136 | // A Socket is an implementation of the AF_XDP Linux socket type for reading packets from a device. 137 | type Socket struct { 138 | fd int 139 | umem []byte 140 | fillRing umemRing 141 | rxRing rxTxRing 142 | txRing rxTxRing 143 | completionRing umemRing 144 | qidconfMap *ebpf.Map 145 | xsksMap *ebpf.Map 146 | program *ebpf.Program 147 | ifindex int 148 | numTransmitted int 149 | numFilled int 150 | freeRXDescs, freeTXDescs []bool 151 | options SocketOptions 152 | rxDescs []Desc 153 | getTXDescs, getRXDescs []Desc 154 | } 155 | 156 | // SocketOptions are configuration settings used to bind an XDP socket. 157 | type SocketOptions struct { 158 | NumFrames int 159 | FrameSize int 160 | FillRingNumDescs int 161 | CompletionRingNumDescs int 162 | RxRingNumDescs int 163 | TxRingNumDescs int 164 | } 165 | 166 | // Desc represents an XDP Rx/Tx descriptor. 167 | type Desc unix.XDPDesc 168 | 169 | // Stats contains various counters of the XDP socket, such as numbers of 170 | // sent/received frames. 171 | type Stats struct { 172 | // Filled is the number of items consumed thus far by the Linux kernel 173 | // from the Fill ring queue. 174 | Filled uint64 175 | 176 | // Received is the number of items consumed thus far by the user of 177 | // this package from the Rx ring queue. 178 | Received uint64 179 | 180 | // Transmitted is the number of items consumed thus far by the Linux 181 | // kernel from the Tx ring queue. 182 | Transmitted uint64 183 | 184 | // Completed is the number of items consumed thus far by the user of 185 | // this package from the Completion ring queue. 186 | Completed uint64 187 | 188 | // KernelStats contains the in-kernel statistics of the corresponding 189 | // XDP socket, such as the number of invalid descriptors that were 190 | // submitted into Fill or Tx ring queues. 191 | KernelStats unix.XDPStatistics 192 | } 193 | 194 | // DefaultSocketFlags are the flags which are passed to bind(2) system call 195 | // when the XDP socket is bound, possible values include unix.XDP_SHARED_UMEM, 196 | // unix.XDP_COPY, unix.XDP_ZEROCOPY. 197 | var DefaultSocketFlags uint16 198 | 199 | // DefaultXdpFlags are the flags which are passed when the XDP program is 200 | // attached to the network link, possible values include 201 | // unix.XDP_FLAGS_DRV_MODE, unix.XDP_FLAGS_HW_MODE, unix.XDP_FLAGS_SKB_MODE, 202 | // unix.XDP_FLAGS_UPDATE_IF_NOEXIST. 203 | var DefaultXdpFlags uint32 204 | 205 | func init() { 206 | DefaultSocketFlags = 0 207 | DefaultXdpFlags = 0 208 | } 209 | 210 | // NewSocket returns a new XDP socket attached to the network interface which 211 | // has the given interface, and attached to the given queue on that network 212 | // interface. 213 | func NewSocket(Ifindex int, QueueID int, options *SocketOptions) (xsk *Socket, err error) { 214 | if options == nil { 215 | options = &DefaultSocketOptions 216 | } 217 | xsk = &Socket{fd: -1, ifindex: Ifindex, options: *options} 218 | 219 | xsk.fd, err = syscall.Socket(unix.AF_XDP, syscall.SOCK_RAW, 0) 220 | if err != nil { 221 | return nil, fmt.Errorf("syscall.Socket failed: %v", err) 222 | } 223 | 224 | xsk.umem, err = syscall.Mmap(-1, 0, options.NumFrames*options.FrameSize, 225 | syscall.PROT_READ|syscall.PROT_WRITE, 226 | syscall.MAP_PRIVATE|syscall.MAP_ANONYMOUS|syscall.MAP_POPULATE) 227 | if err != nil { 228 | xsk.Close() 229 | return nil, fmt.Errorf("syscall.Mmap failed: %v", err) 230 | } 231 | 232 | xdpUmemReg := unix.XDPUmemReg{ 233 | Addr: uint64(uintptr(unsafe.Pointer(&xsk.umem[0]))), 234 | Len: uint64(len(xsk.umem)), 235 | Size: uint32(options.FrameSize), 236 | Headroom: 0, 237 | } 238 | 239 | var errno syscall.Errno 240 | var rc uintptr 241 | 242 | rc, _, errno = unix.Syscall6(syscall.SYS_SETSOCKOPT, uintptr(xsk.fd), 243 | unix.SOL_XDP, unix.XDP_UMEM_REG, 244 | uintptr(unsafe.Pointer(&xdpUmemReg)), 245 | unsafe.Sizeof(xdpUmemReg), 0) 246 | if rc != 0 { 247 | xsk.Close() 248 | return nil, fmt.Errorf("unix.SetsockoptUint64 XDP_UMEM_REG failed: %v", errno) 249 | } 250 | 251 | err = syscall.SetsockoptInt(xsk.fd, unix.SOL_XDP, unix.XDP_UMEM_FILL_RING, 252 | options.FillRingNumDescs) 253 | if err != nil { 254 | xsk.Close() 255 | return nil, fmt.Errorf("unix.SetsockoptUint64 XDP_UMEM_FILL_RING failed: %v", err) 256 | } 257 | 258 | err = unix.SetsockoptInt(xsk.fd, unix.SOL_XDP, unix.XDP_UMEM_COMPLETION_RING, 259 | options.CompletionRingNumDescs) 260 | if err != nil { 261 | xsk.Close() 262 | return nil, fmt.Errorf("unix.SetsockoptUint64 XDP_UMEM_COMPLETION_RING failed: %v", err) 263 | } 264 | 265 | var rxRing bool 266 | if options.RxRingNumDescs > 0 { 267 | err = unix.SetsockoptInt(xsk.fd, unix.SOL_XDP, unix.XDP_RX_RING, 268 | options.RxRingNumDescs) 269 | if err != nil { 270 | xsk.Close() 271 | return nil, fmt.Errorf("unix.SetsockoptUint64 XDP_RX_RING failed: %v", err) 272 | } 273 | rxRing = true 274 | } 275 | 276 | var txRing bool 277 | if options.TxRingNumDescs > 0 { 278 | err = unix.SetsockoptInt(xsk.fd, unix.SOL_XDP, unix.XDP_TX_RING, 279 | options.TxRingNumDescs) 280 | if err != nil { 281 | xsk.Close() 282 | return nil, fmt.Errorf("unix.SetsockoptUint64 XDP_TX_RING failed: %v", err) 283 | } 284 | txRing = true 285 | } 286 | 287 | if !(rxRing || txRing) { 288 | return nil, fmt.Errorf("RxRingNumDescs and TxRingNumDescs cannot both be set to zero") 289 | } 290 | 291 | var offsets unix.XDPMmapOffsets 292 | var vallen uint32 293 | vallen = uint32(unsafe.Sizeof(offsets)) 294 | rc, _, errno = unix.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(xsk.fd), 295 | unix.SOL_XDP, unix.XDP_MMAP_OFFSETS, 296 | uintptr(unsafe.Pointer(&offsets)), 297 | uintptr(unsafe.Pointer(&vallen)), 0) 298 | if rc != 0 { 299 | xsk.Close() 300 | return nil, fmt.Errorf("unix.Syscall6 getsockopt XDP_MMAP_OFFSETS failed: %v", errno) 301 | } 302 | 303 | fillRingSlice, err := syscall.Mmap(xsk.fd, unix.XDP_UMEM_PGOFF_FILL_RING, 304 | int(offsets.Fr.Desc+uint64(options.FillRingNumDescs)*uint64(unsafe.Sizeof(uint64(0)))), 305 | syscall.PROT_READ|syscall.PROT_WRITE, 306 | syscall.MAP_SHARED|syscall.MAP_POPULATE) 307 | if err != nil { 308 | xsk.Close() 309 | return nil, fmt.Errorf("syscall.Mmap XDP_UMEM_PGOFF_FILL_RING failed: %v", err) 310 | } 311 | 312 | xsk.fillRing.Producer = (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&fillRingSlice[0])) + uintptr(offsets.Fr.Producer))) 313 | xsk.fillRing.Consumer = (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&fillRingSlice[0])) + uintptr(offsets.Fr.Consumer))) 314 | sh := (*reflect.SliceHeader)(unsafe.Pointer(&xsk.fillRing.Descs)) 315 | sh.Data = uintptr(unsafe.Pointer(&fillRingSlice[0])) + uintptr(offsets.Fr.Desc) 316 | sh.Len = options.FillRingNumDescs 317 | sh.Cap = options.FillRingNumDescs 318 | 319 | completionRingSlice, err := syscall.Mmap(xsk.fd, unix.XDP_UMEM_PGOFF_COMPLETION_RING, 320 | int(offsets.Cr.Desc+uint64(options.CompletionRingNumDescs)*uint64(unsafe.Sizeof(uint64(0)))), 321 | syscall.PROT_READ|syscall.PROT_WRITE, 322 | syscall.MAP_SHARED|syscall.MAP_POPULATE) 323 | if err != nil { 324 | xsk.Close() 325 | return nil, fmt.Errorf("syscall.Mmap XDP_UMEM_PGOFF_COMPLETION_RING failed: %v", err) 326 | } 327 | 328 | xsk.completionRing.Producer = (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&completionRingSlice[0])) + uintptr(offsets.Cr.Producer))) 329 | xsk.completionRing.Consumer = (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&completionRingSlice[0])) + uintptr(offsets.Cr.Consumer))) 330 | sh = (*reflect.SliceHeader)(unsafe.Pointer(&xsk.completionRing.Descs)) 331 | sh.Data = uintptr(unsafe.Pointer(&completionRingSlice[0])) + uintptr(offsets.Cr.Desc) 332 | sh.Len = options.CompletionRingNumDescs 333 | sh.Cap = options.CompletionRingNumDescs 334 | 335 | if rxRing { 336 | rxRingSlice, err := syscall.Mmap(xsk.fd, unix.XDP_PGOFF_RX_RING, 337 | int(offsets.Rx.Desc+uint64(options.RxRingNumDescs)*uint64(unsafe.Sizeof(Desc{}))), 338 | syscall.PROT_READ|syscall.PROT_WRITE, 339 | syscall.MAP_SHARED|syscall.MAP_POPULATE) 340 | if err != nil { 341 | xsk.Close() 342 | return nil, fmt.Errorf("syscall.Mmap XDP_PGOFF_RX_RING failed: %v", err) 343 | } 344 | 345 | xsk.rxRing.Producer = (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&rxRingSlice[0])) + uintptr(offsets.Rx.Producer))) 346 | xsk.rxRing.Consumer = (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&rxRingSlice[0])) + uintptr(offsets.Rx.Consumer))) 347 | sh = (*reflect.SliceHeader)(unsafe.Pointer(&xsk.rxRing.Descs)) 348 | sh.Data = uintptr(unsafe.Pointer(&rxRingSlice[0])) + uintptr(offsets.Rx.Desc) 349 | sh.Len = options.RxRingNumDescs 350 | sh.Cap = options.RxRingNumDescs 351 | 352 | xsk.rxDescs = make([]Desc, 0, options.RxRingNumDescs) 353 | } 354 | 355 | if txRing { 356 | txRingSlice, err := syscall.Mmap(xsk.fd, unix.XDP_PGOFF_TX_RING, 357 | int(offsets.Tx.Desc+uint64(options.TxRingNumDescs)*uint64(unsafe.Sizeof(Desc{}))), 358 | syscall.PROT_READ|syscall.PROT_WRITE, 359 | syscall.MAP_SHARED|syscall.MAP_POPULATE) 360 | if err != nil { 361 | xsk.Close() 362 | return nil, fmt.Errorf("syscall.Mmap XDP_PGOFF_TX_RING failed: %v", err) 363 | } 364 | 365 | xsk.txRing.Producer = (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&txRingSlice[0])) + uintptr(offsets.Tx.Producer))) 366 | xsk.txRing.Consumer = (*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&txRingSlice[0])) + uintptr(offsets.Tx.Consumer))) 367 | sh = (*reflect.SliceHeader)(unsafe.Pointer(&xsk.txRing.Descs)) 368 | sh.Data = uintptr(unsafe.Pointer(&txRingSlice[0])) + uintptr(offsets.Tx.Desc) 369 | sh.Len = options.TxRingNumDescs 370 | sh.Cap = options.TxRingNumDescs 371 | } 372 | 373 | sa := unix.SockaddrXDP{ 374 | Flags: DefaultSocketFlags, 375 | Ifindex: uint32(Ifindex), 376 | QueueID: uint32(QueueID), 377 | } 378 | if err = unix.Bind(xsk.fd, &sa); err != nil { 379 | xsk.Close() 380 | return nil, fmt.Errorf("syscall.Bind SockaddrXDP failed: %v", err) 381 | } 382 | 383 | xsk.freeRXDescs = make([]bool, options.NumFrames) 384 | xsk.freeTXDescs = make([]bool, options.NumFrames) 385 | for i := range xsk.freeRXDescs { 386 | xsk.freeRXDescs[i] = true 387 | } 388 | for i := range xsk.freeTXDescs { 389 | xsk.freeTXDescs[i] = true 390 | } 391 | xsk.getTXDescs = make([]Desc, 0, options.CompletionRingNumDescs) 392 | xsk.getRXDescs = make([]Desc, 0, options.FillRingNumDescs) 393 | 394 | return xsk, nil 395 | } 396 | 397 | // Fill submits the given descriptors to be filled (i.e. to receive frames into) 398 | // it returns how many descriptors where actually put onto Fill ring queue. 399 | // The descriptors can be acquired either by calling the GetDescs() method or 400 | // by calling Receive() method. 401 | func (xsk *Socket) Fill(descs []Desc) int { 402 | numFreeSlots := xsk.NumFreeFillSlots() 403 | if numFreeSlots < len(descs) { 404 | descs = descs[:numFreeSlots] 405 | } 406 | 407 | prod := *xsk.fillRing.Producer 408 | for _, desc := range descs { 409 | xsk.fillRing.Descs[prod&uint32(xsk.options.FillRingNumDescs-1)] = desc.Addr 410 | prod++ 411 | xsk.freeRXDescs[desc.Addr/uint64(xsk.options.FrameSize)] = false 412 | } 413 | //fencer.SFence() 414 | *xsk.fillRing.Producer = prod 415 | 416 | xsk.numFilled += len(descs) 417 | 418 | return len(descs) 419 | } 420 | 421 | // Receive returns the descriptors which were filled, i.e. into which frames 422 | // were received into. 423 | func (xsk *Socket) Receive(num int) []Desc { 424 | numAvailable := xsk.NumReceived() 425 | if num > int(numAvailable) { 426 | num = int(numAvailable) 427 | } 428 | 429 | descs := xsk.rxDescs[:0] 430 | cons := *xsk.rxRing.Consumer 431 | //fencer.LFence() 432 | for i := 0; i < num; i++ { 433 | descs = append(descs, xsk.rxRing.Descs[cons&uint32(xsk.options.RxRingNumDescs-1)]) 434 | cons++ 435 | xsk.freeRXDescs[descs[i].Addr/uint64(xsk.options.FrameSize)] = true 436 | } 437 | //fencer.MFence() 438 | *xsk.rxRing.Consumer = cons 439 | 440 | xsk.numFilled -= len(descs) 441 | 442 | return descs 443 | } 444 | 445 | // Transmit submits the given descriptors to be sent out, it returns how many 446 | // descriptors were actually pushed onto the Tx ring queue. 447 | // The descriptors can be acquired either by calling the GetDescs() method or 448 | // by calling Receive() method. 449 | func (xsk *Socket) Transmit(descs []Desc) (numSubmitted int) { 450 | numFreeSlots := xsk.NumFreeTxSlots() 451 | if len(descs) > numFreeSlots { 452 | descs = descs[:numFreeSlots] 453 | } 454 | 455 | prod := *xsk.txRing.Producer 456 | for _, desc := range descs { 457 | xsk.txRing.Descs[prod&uint32(xsk.options.TxRingNumDescs-1)] = desc 458 | prod++ 459 | xsk.freeTXDescs[desc.Addr/uint64(xsk.options.FrameSize)] = false 460 | } 461 | //fencer.SFence() 462 | *xsk.txRing.Producer = prod 463 | 464 | xsk.numTransmitted += len(descs) 465 | 466 | numSubmitted = len(descs) 467 | 468 | var rc uintptr 469 | var errno syscall.Errno 470 | for { 471 | rc, _, errno = unix.Syscall6(syscall.SYS_SENDTO, 472 | uintptr(xsk.fd), 473 | 0, 0, 474 | uintptr(unix.MSG_DONTWAIT), 475 | 0, 0) 476 | if rc != 0 { 477 | switch errno { 478 | case unix.EINTR: 479 | // try again 480 | case unix.EAGAIN: 481 | return 482 | case unix.EBUSY: // "completed but not sent" 483 | return 484 | default: 485 | panic(fmt.Errorf("sendto failed with rc=%d and errno=%d", rc, errno)) 486 | } 487 | } else { 488 | break 489 | } 490 | } 491 | 492 | return 493 | } 494 | 495 | // FD returns the file descriptor associated with this xdp.Socket which can be 496 | // used e.g. to do polling. 497 | func (xsk *Socket) FD() int { 498 | return xsk.fd 499 | } 500 | 501 | // Poll blocks until kernel informs us that it has either received 502 | // or completed (i.e. actually sent) some frames that were previously submitted 503 | // using Fill() or Transmit() methods. 504 | // The numReceived return value can be used as the argument for subsequent 505 | // Receive() method call. 506 | func (xsk *Socket) Poll(timeout int) (numReceived int, numCompleted int, err error) { 507 | var events int16 508 | if xsk.numFilled > 0 { 509 | events |= unix.POLLIN 510 | } 511 | if xsk.numTransmitted > 0 { 512 | events |= unix.POLLOUT 513 | } 514 | if events == 0 { 515 | return 516 | } 517 | 518 | var pfds [1]unix.PollFd 519 | pfds[0].Fd = int32(xsk.fd) 520 | pfds[0].Events = events 521 | for err = unix.EINTR; err == unix.EINTR; { 522 | _, err = unix.Poll(pfds[:], timeout) 523 | } 524 | if err != nil { 525 | return 0, 0, err 526 | } 527 | 528 | numReceived = xsk.NumReceived() 529 | if numCompleted = xsk.NumCompleted(); numCompleted > 0 { 530 | xsk.Complete(numCompleted) 531 | } 532 | 533 | return 534 | } 535 | 536 | // GetDescs returns up to n descriptors which are not currently in use. 537 | // if rx is true, return desc in first half of umem, 2nd half otherwise 538 | func (xsk *Socket) GetDescs(n int, rx bool) []Desc { 539 | if n > cap(xsk.getRXDescs) { 540 | n = cap(xsk.getRXDescs) 541 | } 542 | if !rx { 543 | if n > cap(xsk.getTXDescs) { 544 | n = cap(xsk.getTXDescs) 545 | } 546 | } 547 | // numOfUMEMChunks := len(xsk.freeRXDescs) / 2 548 | // if n > numOfUMEMChunks { 549 | // n = numOfUMEMChunks 550 | // } 551 | 552 | descs := xsk.getRXDescs[:0] 553 | j := 0 554 | start := 0 555 | end := cap(xsk.getRXDescs) 556 | freeList := xsk.freeRXDescs 557 | if !rx { 558 | start = cap(xsk.getRXDescs) 559 | end = len(xsk.freeTXDescs) 560 | freeList = xsk.freeTXDescs 561 | descs = xsk.getTXDescs[:0] 562 | } 563 | for i := start; i < end && j < n; i++ { 564 | if freeList[i] == true { 565 | descs = append(descs, Desc{ 566 | Addr: uint64(i) * uint64(xsk.options.FrameSize), 567 | Len: uint32(xsk.options.FrameSize), 568 | }) 569 | j++ 570 | } 571 | } 572 | return descs 573 | } 574 | 575 | // GetFrame returns the buffer containing the frame corresponding to the given 576 | // descriptor. The returned byte slice points to the actual buffer of the 577 | // corresponding frame, so modiyfing this slice modifies the frame contents. 578 | func (xsk *Socket) GetFrame(d Desc) []byte { 579 | return xsk.umem[d.Addr : d.Addr+uint64(d.Len)] 580 | } 581 | 582 | // Close closes and frees the resources allocated by the Socket. 583 | func (xsk *Socket) Close() error { 584 | allErrors := []error{} 585 | var err error 586 | 587 | if xsk.fd != -1 { 588 | if err = unix.Close(xsk.fd); err != nil { 589 | allErrors = append(allErrors, fmt.Errorf("failed to close XDP socket: %v", err)) 590 | } 591 | xsk.fd = -1 592 | 593 | var sh *reflect.SliceHeader 594 | 595 | sh = (*reflect.SliceHeader)(unsafe.Pointer(&xsk.completionRing.Descs)) 596 | sh.Data = uintptr(0) 597 | sh.Len = 0 598 | sh.Cap = 0 599 | 600 | sh = (*reflect.SliceHeader)(unsafe.Pointer(&xsk.txRing.Descs)) 601 | sh.Data = uintptr(0) 602 | sh.Len = 0 603 | sh.Cap = 0 604 | 605 | sh = (*reflect.SliceHeader)(unsafe.Pointer(&xsk.rxRing.Descs)) 606 | sh.Data = uintptr(0) 607 | sh.Len = 0 608 | sh.Cap = 0 609 | 610 | sh = (*reflect.SliceHeader)(unsafe.Pointer(&xsk.fillRing.Descs)) 611 | sh.Data = uintptr(0) 612 | sh.Len = 0 613 | sh.Cap = 0 614 | } 615 | 616 | if xsk.umem != nil { 617 | if err := syscall.Munmap(xsk.umem); err != nil { 618 | allErrors = append(allErrors, fmt.Errorf("failed to unmap the UMEM: %v", err)) 619 | } 620 | xsk.umem = nil 621 | } 622 | 623 | if len(allErrors) > 0 { 624 | return allErrors[0] 625 | } 626 | 627 | return nil 628 | } 629 | 630 | // Complete consumes up to n descriptors from the Completion ring queue to 631 | // which the kernel produces when it has actually transmitted a descriptor it 632 | // got from Tx ring queue. 633 | // You should use this method if you are doing polling on the xdp.Socket file 634 | // descriptor yourself, rather than using the Poll() method. 635 | func (xsk *Socket) Complete(n int) { 636 | cons := *xsk.completionRing.Consumer 637 | //fencer.LFence() 638 | for i := 0; i < n; i++ { 639 | addr := xsk.completionRing.Descs[cons&uint32(xsk.options.CompletionRingNumDescs-1)] 640 | cons++ 641 | xsk.freeTXDescs[addr/uint64(xsk.options.FrameSize)] = true 642 | } 643 | //fencer.MFence() 644 | *xsk.completionRing.Consumer = cons 645 | 646 | xsk.numTransmitted -= n 647 | } 648 | 649 | // NumFreeFillSlots returns how many free slots are available on the Fill ring 650 | // queue, i.e. the queue to which we produce descriptors which should be filled 651 | // by the kernel with incoming frames. 652 | func (xsk *Socket) NumFreeFillSlots() int { 653 | prod := *xsk.fillRing.Producer 654 | cons := *xsk.fillRing.Consumer 655 | max := uint32(xsk.options.FillRingNumDescs) 656 | 657 | n := max - (prod - cons) 658 | if n > max { 659 | n = max 660 | } 661 | 662 | return int(n) 663 | } 664 | 665 | // NumFreeTxSlots returns how many free slots are available on the Tx ring 666 | // queue, i.e. the queue to which we produce descriptors which should be 667 | // transmitted by the kernel to the wire. 668 | func (xsk *Socket) NumFreeTxSlots() int { 669 | prod := *xsk.txRing.Producer 670 | cons := *xsk.txRing.Consumer 671 | max := uint32(xsk.options.TxRingNumDescs) 672 | 673 | n := max - (prod - cons) 674 | if n > max { 675 | n = max 676 | } 677 | 678 | return int(n) 679 | } 680 | 681 | // NumReceived returns how many descriptors are there on the Rx ring queue 682 | // which were produced by the kernel and which we have not yet consumed. 683 | func (xsk *Socket) NumReceived() int { 684 | prod := *xsk.rxRing.Producer 685 | cons := *xsk.rxRing.Consumer 686 | max := uint32(xsk.options.RxRingNumDescs) 687 | 688 | n := prod - cons 689 | if n > max { 690 | n = max 691 | } 692 | 693 | return int(n) 694 | } 695 | 696 | // NumCompleted returns how many descriptors are there on the Completion ring 697 | // queue which were produced by the kernel and which we have not yet consumed. 698 | func (xsk *Socket) NumCompleted() int { 699 | prod := *xsk.completionRing.Producer 700 | cons := *xsk.completionRing.Consumer 701 | max := uint32(xsk.options.CompletionRingNumDescs) 702 | 703 | n := prod - cons 704 | if n > max { 705 | n = max 706 | } 707 | 708 | return int(n) 709 | } 710 | 711 | // NumFilled returns how many descriptors are there on the Fill ring 712 | // queue which have not yet been consumed by the kernel. 713 | // This method is useful if you're polling the xdp.Socket file descriptor 714 | // yourself, rather than using the Poll() method - if it returns a number 715 | // greater than zero it means you should set the unix.POLLIN flag. 716 | func (xsk *Socket) NumFilled() int { 717 | return xsk.numFilled 718 | } 719 | 720 | // NumTransmitted returns how many descriptors are there on the Tx ring queue 721 | // which have not yet been consumed by the kernel. 722 | // Note that even after the descriptors are consumed by the kernel from the Tx 723 | // ring queue, it doesn't mean that they have actually been sent out on the 724 | // wire, that can be assumed only after the descriptors have been produced by 725 | // the kernel to the Completion ring queue. 726 | // This method is useful if you're polling the xdp.Socket file descriptor 727 | // yourself, rather than using the Poll() method - if it returns a number 728 | // greater than zero it means you should set the unix.POLLOUT flag. 729 | func (xsk *Socket) NumTransmitted() int { 730 | return xsk.numTransmitted 731 | } 732 | 733 | // Stats returns various statistics for this XDP socket. 734 | func (xsk *Socket) Stats() (Stats, error) { 735 | var stats Stats 736 | var size uint64 737 | 738 | stats.Filled = uint64(*xsk.fillRing.Consumer) 739 | stats.Received = uint64(*xsk.rxRing.Consumer) 740 | if xsk.txRing.Consumer != nil { 741 | stats.Transmitted = uint64(*xsk.txRing.Consumer) 742 | } 743 | if xsk.completionRing.Consumer != nil { 744 | stats.Completed = uint64(*xsk.completionRing.Consumer) 745 | } 746 | size = uint64(unsafe.Sizeof(stats.KernelStats)) 747 | rc, _, errno := unix.Syscall6(syscall.SYS_GETSOCKOPT, 748 | uintptr(xsk.fd), 749 | unix.SOL_XDP, unix.XDP_STATISTICS, 750 | uintptr(unsafe.Pointer(&stats.KernelStats)), 751 | uintptr(unsafe.Pointer(&size)), 0) 752 | if rc != 0 { 753 | return stats, fmt.Errorf("getsockopt XDP_STATISTICS failed with errno %d", errno) 754 | } 755 | return stats, nil 756 | } 757 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/ipproto_bpfeb.go: -------------------------------------------------------------------------------- 1 | // Code generated by bpf2go; DO NOT EDIT. 2 | // +build armbe arm64be mips mips64 mips64p32 ppc64 s390 s390x sparc sparc64 3 | 4 | package ebpf 5 | 6 | import ( 7 | "bytes" 8 | "fmt" 9 | "io" 10 | 11 | "github.com/cilium/ebpf" 12 | ) 13 | 14 | // loadIpproto returns the embedded CollectionSpec for ipproto. 15 | func loadIpproto() (*ebpf.CollectionSpec, error) { 16 | reader := bytes.NewReader(_IpprotoBytes) 17 | spec, err := ebpf.LoadCollectionSpecFromReader(reader) 18 | if err != nil { 19 | return nil, fmt.Errorf("can't load ipproto: %w", err) 20 | } 21 | 22 | return spec, err 23 | } 24 | 25 | // loadIpprotoObjects loads ipproto and converts it into a struct. 26 | // 27 | // The following types are suitable as obj argument: 28 | // 29 | // *ipprotoObjects 30 | // *ipprotoPrograms 31 | // *ipprotoMaps 32 | // 33 | // See ebpf.CollectionSpec.LoadAndAssign documentation for details. 34 | func loadIpprotoObjects(obj interface{}, opts *ebpf.CollectionOptions) error { 35 | spec, err := loadIpproto() 36 | if err != nil { 37 | return err 38 | } 39 | 40 | return spec.LoadAndAssign(obj, opts) 41 | } 42 | 43 | // ipprotoSpecs contains maps and programs before they are loaded into the kernel. 44 | // 45 | // It can be passed ebpf.CollectionSpec.Assign. 46 | type ipprotoSpecs struct { 47 | ipprotoProgramSpecs 48 | ipprotoMapSpecs 49 | } 50 | 51 | // ipprotoSpecs contains programs before they are loaded into the kernel. 52 | // 53 | // It can be passed ebpf.CollectionSpec.Assign. 54 | type ipprotoProgramSpecs struct { 55 | XdpSockProg *ebpf.ProgramSpec `ebpf:"xdp_sock_prog"` 56 | } 57 | 58 | // ipprotoMapSpecs contains maps before they are loaded into the kernel. 59 | // 60 | // It can be passed ebpf.CollectionSpec.Assign. 61 | type ipprotoMapSpecs struct { 62 | QidconfMap *ebpf.MapSpec `ebpf:"qidconf_map"` 63 | XsksMap *ebpf.MapSpec `ebpf:"xsks_map"` 64 | } 65 | 66 | // ipprotoObjects contains all objects after they have been loaded into the kernel. 67 | // 68 | // It can be passed to loadIpprotoObjects or ebpf.CollectionSpec.LoadAndAssign. 69 | type ipprotoObjects struct { 70 | ipprotoPrograms 71 | ipprotoMaps 72 | } 73 | 74 | func (o *ipprotoObjects) Close() error { 75 | return _IpprotoClose( 76 | &o.ipprotoPrograms, 77 | &o.ipprotoMaps, 78 | ) 79 | } 80 | 81 | // ipprotoMaps contains all maps after they have been loaded into the kernel. 82 | // 83 | // It can be passed to loadIpprotoObjects or ebpf.CollectionSpec.LoadAndAssign. 84 | type ipprotoMaps struct { 85 | QidconfMap *ebpf.Map `ebpf:"qidconf_map"` 86 | XsksMap *ebpf.Map `ebpf:"xsks_map"` 87 | } 88 | 89 | func (m *ipprotoMaps) Close() error { 90 | return _IpprotoClose( 91 | m.QidconfMap, 92 | m.XsksMap, 93 | ) 94 | } 95 | 96 | // ipprotoPrograms contains all programs after they have been loaded into the kernel. 97 | // 98 | // It can be passed to loadIpprotoObjects or ebpf.CollectionSpec.LoadAndAssign. 99 | type ipprotoPrograms struct { 100 | XdpSockProg *ebpf.Program `ebpf:"xdp_sock_prog"` 101 | } 102 | 103 | func (p *ipprotoPrograms) Close() error { 104 | return _IpprotoClose( 105 | p.XdpSockProg, 106 | ) 107 | } 108 | 109 | func _IpprotoClose(closers ...io.Closer) error { 110 | for _, closer := range closers { 111 | if err := closer.Close(); err != nil { 112 | return err 113 | } 114 | } 115 | return nil 116 | } 117 | 118 | // Do not access this directly. 119 | var _IpprotoBytes = []byte("\x7f\x45\x4c\x46\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\xf7\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x27\x40\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x40\x00\x17\x00\x01\xbf\x61\x00\x00\x00\x00\x00\x00\x61\x16\x00\x10\x00\x00\x00\x00\x63\xa1\xff\xfc\x00\x00\x00\x00\xbf\x2a\x00\x00\x00\x00\x00\x00\x07\x20\x00\x00\xff\xff\xff\xfc\x18\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x00\x00\x00\x01\xbf\x10\x00\x00\x00\x00\x00\x00\xb7\x00\x00\x00\x00\x00\x00\x02\x15\x10\x00\x25\x00\x00\x00\x00\x61\x36\x00\x04\x00\x00\x00\x00\x61\x26\x00\x00\x00\x00\x00\x00\xbf\x42\x00\x00\x00\x00\x00\x00\x07\x40\x00\x00\x00\x00\x00\x0e\x2d\x43\x00\x20\x00\x00\x00\x00\x71\x52\x00\x0d\x00\x00\x00\x00\x71\x42\x00\x0c\x00\x00\x00\x00\x67\x40\x00\x00\x00\x00\x00\x08\x4f\x45\x00\x00\x00\x00\x00\x00\x15\x40\x00\x0c\x00\x00\x86\xdd\x55\x40\x00\x1a\x00\x00\x08\x00\xbf\x42\x00\x00\x00\x00\x00\x00\x07\x40\x00\x00\x00\x00\x00\x22\x2d\x43\x00\x17\x00\x00\x00\x00\x71\x22\x00\x17\x00\x00\x00\x00\x18\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x71\x33\x00\x00\x00\x00\x00\x00\x5d\x23\x00\x12\x00\x00\x00\x00\x61\x11\x00\x00\x00\x00\x00\x00\x15\x10\x00\x10\x00\x00\x00\x00\x05\x00\x00\x0a\x00\x00\x00\x00\xbf\x42\x00\x00\x00\x00\x00\x00\x07\x40\x00\x00\x00\x00\x00\x36\x2d\x43\x00\x0c\x00\x00\x00\x00\x71\x22\x00\x14\x00\x00\x00\x00\x18\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x71\x33\x00\x00\x00\x00\x00\x00\x5d\x23\x00\x07\x00\x00\x00\x00\x61\x11\x00\x00\x00\x00\x00\x00\x15\x10\x00\x05\x00\x00\x00\x00\x61\x2a\xff\xfc\x00\x00\x00\x00\x18\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb7\x30\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x00\x00\x00\x33\x95\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x40\x00\x00\x00\x00\x01\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x20\x6f\x72\x20\x42\x53\x44\x2d\x32\x2d\x43\x6c\x61\x75\x73\x65\x00\x00\x2e\x2f\x73\x69\x6e\x67\x6c\x65\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x5f\x66\x69\x6c\x74\x65\x72\x2e\x63\x00\x2e\x00\x78\x73\x6b\x73\x5f\x6d\x61\x70\x00\x74\x79\x70\x65\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\x00\x6b\x65\x79\x5f\x73\x69\x7a\x65\x00\x76\x61\x6c\x75\x65\x5f\x73\x69\x7a\x65\x00\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x65\x73\x00\x6d\x61\x70\x5f\x66\x6c\x61\x67\x73\x00\x62\x70\x66\x5f\x6d\x61\x70\x5f\x64\x65\x66\x00\x71\x69\x64\x63\x6f\x6e\x66\x5f\x6d\x61\x70\x00\x5f\x5f\x6c\x69\x63\x65\x6e\x73\x65\x00\x63\x68\x61\x72\x00\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\x00\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x00\x50\x52\x4f\x54\x4f\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\x00\x62\x70\x66\x5f\x72\x65\x64\x69\x72\x65\x63\x74\x5f\x6d\x61\x70\x00\x6c\x6f\x6e\x67\x20\x69\x6e\x74\x00\x5f\x5f\x75\x33\x32\x00\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\x00\x5f\x5f\x75\x36\x34\x00\x58\x44\x50\x5f\x41\x42\x4f\x52\x54\x45\x44\x00\x58\x44\x50\x5f\x44\x52\x4f\x50\x00\x58\x44\x50\x5f\x50\x41\x53\x53\x00\x58\x44\x50\x5f\x54\x58\x00\x58\x44\x50\x5f\x52\x45\x44\x49\x52\x45\x43\x54\x00\x78\x64\x70\x5f\x61\x63\x74\x69\x6f\x6e\x00\x78\x64\x70\x5f\x73\x6f\x63\x6b\x5f\x70\x72\x6f\x67\x00\x69\x6e\x74\x00\x63\x74\x78\x00\x64\x61\x74\x61\x00\x64\x61\x74\x61\x5f\x65\x6e\x64\x00\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\x00\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\x65\x78\x00\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x69\x6e\x64\x65\x78\x00\x78\x64\x70\x5f\x6d\x64\x00\x69\x6e\x64\x65\x78\x00\x71\x69\x64\x63\x6f\x6e\x66\x00\x65\x74\x68\x00\x68\x5f\x64\x65\x73\x74\x00\x68\x5f\x73\x6f\x75\x72\x63\x65\x00\x68\x5f\x70\x72\x6f\x74\x6f\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x73\x68\x6f\x72\x74\x00\x5f\x5f\x75\x31\x36\x00\x5f\x5f\x62\x65\x31\x36\x00\x65\x74\x68\x68\x64\x72\x00\x69\x70\x00\x69\x68\x6c\x00\x5f\x5f\x75\x38\x00\x76\x65\x72\x73\x69\x6f\x6e\x00\x74\x6f\x73\x00\x74\x6f\x74\x5f\x6c\x65\x6e\x00\x69\x64\x00\x66\x72\x61\x67\x5f\x6f\x66\x66\x00\x74\x74\x6c\x00\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x00\x63\x68\x65\x63\x6b\x00\x5f\x5f\x73\x75\x6d\x31\x36\x00\x73\x61\x64\x64\x72\x00\x5f\x5f\x62\x65\x33\x32\x00\x64\x61\x64\x64\x72\x00\x69\x70\x68\x64\x72\x00\x70\x72\x69\x6f\x72\x69\x74\x79\x00\x66\x6c\x6f\x77\x5f\x6c\x62\x6c\x00\x70\x61\x79\x6c\x6f\x61\x64\x5f\x6c\x65\x6e\x00\x6e\x65\x78\x74\x68\x64\x72\x00\x68\x6f\x70\x5f\x6c\x69\x6d\x69\x74\x00\x69\x6e\x36\x5f\x75\x00\x75\x36\x5f\x61\x64\x64\x72\x38\x00\x75\x36\x5f\x61\x64\x64\x72\x31\x36\x00\x75\x36\x5f\x61\x64\x64\x72\x33\x32\x00\x69\x6e\x36\x5f\x61\x64\x64\x72\x00\x69\x70\x76\x36\x68\x64\x72\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x01\x51\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x88\x00\x01\x56\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x18\x00\x01\x51\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x01\x58\x00\x02\x7a\x04\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x88\x00\x02\x7a\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x48\x00\x00\x00\x00\x00\x00\x00\xf8\x00\x01\x51\x00\x00\x00\x00\x00\x00\x01\x08\x00\x00\x00\x00\x00\x00\x01\x50\x00\x01\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x00\x00\x00\x00\x00\x00\x00\xd0\x00\x01\x52\x00\x00\x00\x00\x00\x00\x01\x08\x00\x00\x00\x00\x00\x00\x01\x28\x00\x01\x52\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x01\x53\x00\x00\x00\x00\x00\x00\x01\x08\x00\x00\x00\x00\x00\x00\x01\x38\x00\x01\x53\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x01\x54\x00\x00\x00\x00\x00\x00\x01\x08\x00\x00\x00\x00\x00\x00\x01\x10\x00\x01\x54\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x00\xd0\x00\x03\x72\x0e\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x18\x00\x00\x00\x00\x00\x00\x01\x28\x00\x03\x72\x0e\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x11\x01\x25\x0e\x13\x05\x03\x0e\x10\x17\x1b\x0e\x11\x01\x12\x06\x00\x00\x02\x34\x00\x03\x0e\x49\x13\x3f\x19\x3a\x0b\x3b\x0b\x02\x18\x00\x00\x03\x13\x01\x03\x0e\x0b\x0b\x3a\x0b\x3b\x0b\x00\x00\x04\x0d\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x0b\x38\x0b\x00\x00\x05\x24\x00\x03\x0e\x3e\x0b\x0b\x0b\x00\x00\x06\x01\x01\x49\x13\x00\x00\x07\x21\x00\x49\x13\x37\x0b\x00\x00\x08\x24\x00\x03\x0e\x0b\x0b\x3e\x0b\x00\x00\x09\x34\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x0b\x00\x00\x0a\x0f\x00\x49\x13\x00\x00\x0b\x15\x01\x49\x13\x27\x19\x00\x00\x0c\x05\x00\x49\x13\x00\x00\x0d\x0f\x00\x00\x00\x0e\x26\x00\x00\x00\x0f\x34\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x0b\x02\x18\x00\x00\x10\x26\x00\x49\x13\x00\x00\x11\x35\x00\x49\x13\x00\x00\x12\x34\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x05\x00\x00\x13\x16\x00\x49\x13\x03\x0e\x3a\x0b\x3b\x0b\x00\x00\x14\x04\x01\x49\x13\x03\x0e\x0b\x0b\x3a\x0b\x3b\x05\x00\x00\x15\x28\x00\x03\x0e\x1c\x0f\x00\x00\x16\x2e\x01\x11\x01\x12\x06\x40\x18\x97\x42\x19\x03\x0e\x3a\x0b\x3b\x0b\x27\x19\x49\x13\x3f\x19\x00\x00\x17\x05\x00\x02\x17\x03\x0e\x3a\x0b\x3b\x0b\x49\x13\x00\x00\x18\x34\x00\x02\x17\x03\x0e\x3a\x0b\x3b\x0b\x49\x13\x00\x00\x19\x34\x00\x03\x0e\x3a\x0b\x3b\x0b\x49\x13\x00\x00\x1a\x0b\x01\x11\x01\x12\x06\x00\x00\x1b\x13\x01\x03\x0e\x0b\x0b\x3a\x0b\x3b\x05\x00\x00\x1c\x0d\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x05\x38\x0b\x00\x00\x1d\x0d\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x0b\x0b\x0b\x0d\x0b\x0c\x0b\x38\x0b\x00\x00\x1e\x17\x01\x0b\x0b\x3a\x0b\x3b\x0b\x00\x00\x00\x00\x00\x04\x9a\x00\x04\x00\x00\x00\x00\x08\x01\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x88\x02\x00\x00\x00\x00\x00\x00\x00\x3f\x02\x18\x09\x03\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x14\x01\x39\x04\x00\x00\x00\x00\x00\x00\x00\x84\x01\x3a\x00\x04\x00\x00\x00\x00\x00\x00\x00\x84\x01\x3b\x04\x04\x00\x00\x00\x00\x00\x00\x00\x84\x01\x3c\x08\x04\x00\x00\x00\x00\x00\x00\x00\x84\x01\x3d\x0c\x04\x00\x00\x00\x00\x00\x00\x00\x84\x01\x3e\x10\x00\x05\x00\x00\x00\x00\x07\x04\x02\x00\x00\x00\x00\x00\x00\x00\x3f\x02\x1f\x09\x03\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xb5\x02\x4f\x09\x03\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\xc1\x07\x00\x00\x00\xc8\x19\x00\x05\x00\x00\x00\x00\x06\x01\x08\x00\x00\x00\x00\x08\x07\x09\x00\x00\x00\x00\x00\x00\x00\xda\x03\x2a\x0a\x00\x00\x00\xdf\x0b\x00\x00\x00\xef\x0c\x00\x00\x00\xef\x0c\x00\x00\x00\xf0\x00\x0d\x0a\x00\x00\x00\xf5\x0e\x0f\x00\x00\x00\x00\x00\x00\x01\x0b\x02\x10\x09\x03\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x01\x10\x11\x00\x00\x01\x15\x05\x00\x00\x00\x00\x08\x01\x12\x00\x00\x00\x00\x00\x00\x01\x28\x03\x04\xff\x0a\x00\x00\x01\x2d\x0b\x00\x00\x01\x42\x0c\x00\x00\x00\xef\x0c\x00\x00\x01\x49\x0c\x00\x00\x01\x54\x00\x05\x00\x00\x00\x00\x05\x08\x13\x00\x00\x00\x84\x00\x00\x00\x00\x04\x1b\x13\x00\x00\x01\x5f\x00\x00\x00\x00\x04\x1f\x05\x00\x00\x00\x00\x07\x08\x14\x00\x00\x00\x84\x00\x00\x00\x00\x04\x05\x0d\xa1\x15\x00\x00\x00\x00\x00\x15\x00\x00\x00\x00\x01\x15\x00\x00\x00\x00\x02\x15\x00\x00\x00\x00\x03\x15\x00\x00\x00\x00\x04\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x88\x01\x5a\x00\x00\x00\x00\x02\x27\x00\x00\x02\x4b\x17\x00\x00\x00\x00\x00\x00\x00\x00\x02\x27\x00\x00\x02\x52\x18\x00\x00\x00\x36\x00\x00\x00\x00\x02\x2a\x00\x00\x02\x4b\x18\x00\x00\x00\x81\x00\x00\x00\x00\x02\x2a\x00\x00\x02\xa2\x19\x00\x00\x00\x00\x02\x33\x00\x00\x00\xef\x18\x00\x00\x00\xb7\x00\x00\x00\x00\x02\x35\x00\x00\x02\xa7\x18\x00\x00\x00\xed\x00\x00\x00\x00\x02\x34\x00\x00\x00\xef\x18\x00\x00\x01\x23\x00\x00\x00\x00\x02\x36\x00\x00\x02\xf0\x1a\x00\x00\x00\x00\x00\x00\x00\xb0\x00\x00\x00\x50\x18\x00\x00\x01\x59\x00\x00\x00\x00\x02\x39\x00\x00\x03\x02\x00\x1a\x00\x00\x00\x00\x00\x00\x01\x08\x00\x00\x00\x50\x18\x00\x00\x01\x7e\x00\x00\x00\x00\x02\x41\x00\x00\x03\xbb\x00\x00\x05\x00\x00\x00\x00\x05\x04\x0a\x00\x00\x02\x57\x1b\x00\x00\x00\x00\x14\x05\x0d\xac\x1c\x00\x00\x00\x00\x00\x00\x01\x49\x05\x0d\xad\x00\x1c\x00\x00\x00\x00\x00\x00\x01\x49\x05\x0d\xae\x04\x1c\x00\x00\x00\x00\x00\x00\x01\x49\x05\x0d\xaf\x08\x1c\x00\x00\x00\x00\x00\x00\x01\x49\x05\x0d\xb1\x0c\x1c\x00\x00\x00\x00\x00\x00\x01\x49\x05\x0d\xb2\x10\x00\x0a\x00\x00\x02\x4b\x0a\x00\x00\x02\xac\x03\x00\x00\x00\x00\x0e\x06\xa2\x04\x00\x00\x00\x00\x00\x00\x02\xd9\x06\xa3\x00\x04\x00\x00\x00\x00\x00\x00\x02\xd9\x06\xa4\x06\x04\x00\x00\x00\x00\x00\x00\x02\xe5\x06\xa5\x0c\x00\x06\x00\x00\x01\x15\x07\x00\x00\x00\xc8\x06\x00\x13\x00\x00\x02\xf0\x00\x00\x00\x00\x07\x19\x13\x00\x00\x02\xfb\x00\x00\x00\x00\x04\x18\x05\x00\x00\x00\x00\x07\x02\x0a\x00\x00\x03\x07\x03\x00\x00\x00\x00\x14\x08\x56\x1d\x00\x00\x00\x00\x00\x00\x03\x9a\x08\x58\x01\x04\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x03\x9a\x08\x59\x01\x04\x04\x00\x04\x00\x00\x00\x00\x00\x00\x03\x9a\x08\x60\x01\x04\x00\x00\x00\x00\x00\x00\x02\xe5\x08\x61\x02\x04\x00\x00\x00\x00\x00\x00\x02\xe5\x08\x62\x04\x04\x00\x00\x00\x00\x00\x00\x02\xe5\x08\x63\x06\x04\x00\x00\x00\x00\x00\x00\x03\x9a\x08\x64\x08\x04\x00\x00\x00\x00\x00\x00\x03\x9a\x08\x65\x09\x04\x00\x00\x00\x00\x00\x00\x03\xa5\x08\x66\x0a\x04\x00\x00\x00\x00\x00\x00\x03\xb0\x08\x67\x0c\x04\x00\x00\x00\x00\x00\x00\x03\xb0\x08\x68\x10\x00\x13\x00\x00\x01\x15\x00\x00\x00\x00\x04\x15\x13\x00\x00\x02\xf0\x00\x00\x00\x00\x07\x1f\x13\x00\x00\x01\x49\x00\x00\x00\x00\x07\x1b\x0a\x00\x00\x03\xc0\x03\x00\x00\x00\x00\x28\x09\x74\x1d\x00\x00\x00\x00\x00\x00\x03\x9a\x09\x76\x01\x04\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x03\x9a\x09\x77\x01\x04\x04\x00\x04\x00\x00\x00\x00\x00\x00\x04\x2f\x09\x7e\x01\x04\x00\x00\x00\x00\x00\x00\x02\xe5\x09\x80\x04\x04\x00\x00\x00\x00\x00\x00\x03\x9a\x09\x81\x06\x04\x00\x00\x00\x00\x00\x00\x03\x9a\x09\x82\x07\x04\x00\x00\x00\x00\x00\x00\x04\x3b\x09\x84\x08\x04\x00\x00\x00\x00\x00\x00\x04\x3b\x09\x85\x18\x00\x06\x00\x00\x03\x9a\x07\x00\x00\x00\xc8\x03\x00\x03\x00\x00\x00\x00\x10\x0a\x21\x04\x00\x00\x00\x00\x00\x00\x04\x4f\x0a\x28\x00\x1e\x10\x0a\x22\x04\x00\x00\x00\x00\x00\x00\x04\x79\x0a\x23\x00\x04\x00\x00\x00\x00\x00\x00\x04\x85\x0a\x25\x00\x04\x00\x00\x00\x00\x00\x00\x04\x91\x0a\x26\x00\x00\x00\x06\x00\x00\x03\x9a\x07\x00\x00\x00\xc8\x10\x00\x06\x00\x00\x02\xe5\x07\x00\x00\x00\xc8\x08\x00\x06\x00\x00\x03\xb0\x07\x00\x00\x00\xc8\x04\x00\x00\xeb\x9f\x01\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x01\xdc\x00\x00\x01\xdc\x00\x00\x03\x1e\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x04\x00\x00\x05\x00\x00\x00\x14\x00\x00\x00\x08\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x03\x00\x00\x00\x20\x00\x00\x00\x16\x00\x00\x00\x03\x00\x00\x00\x40\x00\x00\x00\x20\x00\x00\x00\x03\x00\x00\x00\x60\x00\x00\x00\x30\x00\x00\x00\x03\x00\x00\x00\x80\x00\x00\x00\x3f\x08\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x45\x01\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x20\x00\x00\x00\x00\x0d\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x52\x00\x00\x00\x01\x00\x00\x00\x56\x01\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x20\x00\x00\x00\x5a\x0c\x00\x00\x01\x00\x00\x00\x05\x00\x00\x02\x82\x04\x00\x00\x05\x00\x00\x00\x14\x00\x00\x02\x8e\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x02\x93\x00\x00\x00\x04\x00\x00\x00\x20\x00\x00\x02\x9c\x00\x00\x00\x04\x00\x00\x00\x40\x00\x00\x02\xa7\x00\x00\x00\x04\x00\x00\x00\x60\x00\x00\x02\xb3\x00\x00\x00\x04\x00\x00\x00\x80\x00\x00\x02\xbd\x0e\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x02\xc6\x0e\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x02\xd2\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x08\x00\x00\x02\xe0\x0e\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x02\xe6\x01\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x08\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x11\x00\x00\x00\x19\x00\x00\x02\xeb\x01\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x20\x00\x00\x02\xff\x0e\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x03\x09\x0f\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x03\x11\x0f\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x03\x19\x0f\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x14\x00\x78\x64\x70\x5f\x6d\x64\x00\x64\x61\x74\x61\x00\x64\x61\x74\x61\x5f\x65\x6e\x64\x00\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\x00\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\x65\x78\x00\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x69\x6e\x64\x65\x78\x00\x5f\x5f\x75\x33\x32\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\x00\x63\x74\x78\x00\x69\x6e\x74\x00\x78\x64\x70\x5f\x73\x6f\x63\x6b\x5f\x70\x72\x6f\x67\x00\x78\x64\x70\x5f\x73\x6f\x63\x6b\x00\x2e\x2f\x2e\x2f\x73\x69\x6e\x67\x6c\x65\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x5f\x66\x69\x6c\x74\x65\x72\x2e\x63\x00\x53\x45\x43\x28\x22\x78\x64\x70\x5f\x73\x6f\x63\x6b\x22\x29\x20\x69\x6e\x74\x20\x78\x64\x70\x5f\x73\x6f\x63\x6b\x5f\x70\x72\x6f\x67\x28\x73\x74\x72\x75\x63\x74\x20\x78\x64\x70\x5f\x6d\x64\x20\x2a\x63\x74\x78\x29\x00\x09\x69\x6e\x74\x20\x2a\x71\x69\x64\x63\x6f\x6e\x66\x2c\x20\x69\x6e\x64\x65\x78\x20\x3d\x20\x63\x74\x78\x2d\x3e\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x69\x6e\x64\x65\x78\x3b\x00\x09\x71\x69\x64\x63\x6f\x6e\x66\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x71\x69\x64\x63\x6f\x6e\x66\x5f\x6d\x61\x70\x2c\x20\x26\x69\x6e\x64\x65\x78\x29\x3b\x00\x09\x69\x66\x20\x28\x21\x71\x69\x64\x63\x6f\x6e\x66\x29\x00\x09\x76\x6f\x69\x64\x20\x2a\x64\x61\x74\x61\x5f\x65\x6e\x64\x20\x3d\x20\x28\x76\x6f\x69\x64\x2a\x29\x28\x6c\x6f\x6e\x67\x29\x63\x74\x78\x2d\x3e\x64\x61\x74\x61\x5f\x65\x6e\x64\x3b\x00\x09\x76\x6f\x69\x64\x20\x2a\x64\x61\x74\x61\x20\x3d\x20\x28\x76\x6f\x69\x64\x2a\x29\x28\x6c\x6f\x6e\x67\x29\x63\x74\x78\x2d\x3e\x64\x61\x74\x61\x3b\x00\x09\x69\x66\x20\x28\x28\x76\x6f\x69\x64\x2a\x29\x65\x74\x68\x20\x2b\x20\x73\x69\x7a\x65\x6f\x66\x28\x2a\x65\x74\x68\x29\x20\x3c\x3d\x20\x64\x61\x74\x61\x5f\x65\x6e\x64\x29\x20\x7b\x00\x09\x5f\x5f\x75\x31\x36\x20\x68\x5f\x70\x72\x6f\x74\x6f\x20\x3d\x20\x65\x74\x68\x2d\x3e\x68\x5f\x70\x72\x6f\x74\x6f\x3b\x00\x09\x09\x69\x66\x20\x28\x62\x70\x66\x5f\x68\x74\x6f\x6e\x73\x28\x68\x5f\x70\x72\x6f\x74\x6f\x29\x20\x3d\x3d\x20\x45\x54\x48\x5f\x50\x5f\x49\x50\x29\x20\x7b\x00\x09\x09\x09\x69\x66\x20\x28\x28\x76\x6f\x69\x64\x2a\x29\x69\x70\x20\x2b\x20\x73\x69\x7a\x65\x6f\x66\x28\x2a\x69\x70\x29\x20\x3c\x3d\x20\x64\x61\x74\x61\x5f\x65\x6e\x64\x29\x20\x7b\x00\x09\x09\x09\x09\x69\x66\x20\x28\x69\x70\x2d\x3e\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x3d\x20\x50\x52\x4f\x54\x4f\x29\x20\x7b\x00\x09\x09\x09\x09\x09\x69\x66\x20\x28\x2a\x71\x69\x64\x63\x6f\x6e\x66\x29\x00\x09\x09\x09\x09\x69\x66\x20\x28\x69\x70\x2d\x3e\x6e\x65\x78\x74\x68\x64\x72\x20\x3d\x3d\x20\x50\x52\x4f\x54\x4f\x29\x20\x7b\x00\x7d\x00\x62\x70\x66\x5f\x6d\x61\x70\x5f\x64\x65\x66\x00\x74\x79\x70\x65\x00\x6b\x65\x79\x5f\x73\x69\x7a\x65\x00\x76\x61\x6c\x75\x65\x5f\x73\x69\x7a\x65\x00\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x65\x73\x00\x6d\x61\x70\x5f\x66\x6c\x61\x67\x73\x00\x78\x73\x6b\x73\x5f\x6d\x61\x70\x00\x71\x69\x64\x63\x6f\x6e\x66\x5f\x6d\x61\x70\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\x00\x50\x52\x4f\x54\x4f\x00\x63\x68\x61\x72\x00\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\x00\x5f\x5f\x6c\x69\x63\x65\x6e\x73\x65\x00\x2e\x72\x6f\x64\x61\x74\x61\x00\x6c\x69\x63\x65\x6e\x73\x65\x00\x6d\x61\x70\x73\x00\xeb\x9f\x01\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x14\x00\x00\x01\xcc\x00\x00\x01\xe0\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x68\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x68\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x71\x00\x00\x00\x8e\x00\x00\x9c\x00\x00\x00\x00\x08\x00\x00\x00\x71\x00\x00\x00\xc4\x00\x00\xa8\x1d\x00\x00\x00\x10\x00\x00\x00\x71\x00\x00\x00\xc4\x00\x00\xa8\x10\x00\x00\x00\x20\x00\x00\x00\x71\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x00\x00\x00\x71\x00\x00\x00\xf0\x00\x00\xb8\x0c\x00\x00\x00\x50\x00\x00\x00\x71\x00\x00\x01\x26\x00\x00\xbc\x06\x00\x00\x00\x58\x00\x00\x00\x71\x00\x00\x01\x35\x00\x00\xd0\x25\x00\x00\x00\x60\x00\x00\x00\x71\x00\x00\x01\x63\x00\x00\xcc\x21\x00\x00\x00\x68\x00\x00\x00\x71\x00\x00\x01\x89\x00\x00\xdc\x11\x00\x00\x00\x78\x00\x00\x00\x71\x00\x00\x01\x89\x00\x00\xdc\x06\x00\x00\x00\x80\x00\x00\x00\x71\x00\x00\x01\xb7\x00\x00\xd8\x17\x00\x00\x00\xa0\x00\x00\x00\x71\x00\x00\x01\xd6\x00\x00\xe0\x07\x00\x00\x00\xb0\x00\x00\x00\x71\x00\x00\x01\xfe\x00\x00\xe8\x12\x00\x00\x00\xc0\x00\x00\x00\x71\x00\x00\x01\xfe\x00\x00\xe8\x08\x00\x00\x00\xc8\x00\x00\x00\x71\x00\x00\x02\x2c\x00\x00\xec\x0d\x00\x00\x00\xd0\x00\x00\x00\x71\x00\x00\x02\x2c\x00\x00\xec\x19\x00\x00\x00\xe8\x00\x00\x00\x71\x00\x00\x02\x2c\x00\x00\xec\x09\x00\x00\x00\xf0\x00\x00\x00\x71\x00\x00\x02\x4d\x00\x00\xf0\x0a\x00\x00\x00\xf8\x00\x00\x00\x71\x00\x00\x02\x4d\x00\x00\xf0\x0a\x00\x00\x01\x08\x00\x00\x00\x71\x00\x00\x01\xfe\x00\x01\x08\x12\x00\x00\x01\x18\x00\x00\x00\x71\x00\x00\x01\xfe\x00\x01\x08\x08\x00\x00\x01\x20\x00\x00\x00\x71\x00\x00\x02\x60\x00\x01\x0c\x0d\x00\x00\x01\x28\x00\x00\x00\x71\x00\x00\x02\x60\x00\x01\x0c\x18\x00\x00\x01\x40\x00\x00\x00\x71\x00\x00\x02\x60\x00\x01\x0c\x09\x00\x00\x01\x48\x00\x00\x00\x71\x00\x00\x02\x4d\x00\x01\x10\x0a\x00\x00\x01\x50\x00\x00\x00\x71\x00\x00\x02\x4d\x00\x01\x10\x0a\x00\x00\x01\x58\x00\x00\x00\x71\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x71\x00\x00\x02\x80\x00\x01\x30\x01\x00\x00\x00\x10\x00\x00\x00\x00\x01\x7a\x52\x00\x08\x7c\x0b\x01\x0c\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x88\x00\x00\x00\x00\x00\x00\x01\x6b\x00\x04\x00\x00\x00\xdd\x08\x01\x01\xfb\x0e\x0d\x00\x01\x01\x01\x01\x00\x00\x00\x01\x00\x00\x01\x2e\x2f\x69\x6e\x63\x6c\x75\x64\x65\x2f\x62\x70\x66\x00\x2e\x00\x2f\x75\x73\x72\x2f\x69\x6e\x63\x6c\x75\x64\x65\x2f\x61\x73\x6d\x2d\x67\x65\x6e\x65\x72\x69\x63\x00\x2f\x75\x73\x72\x2f\x69\x6e\x63\x6c\x75\x64\x65\x2f\x6c\x69\x6e\x75\x78\x00\x00\x62\x70\x66\x5f\x68\x65\x6c\x70\x65\x72\x73\x2e\x68\x00\x01\x00\x00\x73\x69\x6e\x67\x6c\x65\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x5f\x66\x69\x6c\x74\x65\x72\x2e\x63\x00\x02\x00\x00\x62\x70\x66\x5f\x68\x65\x6c\x70\x65\x72\x5f\x64\x65\x66\x73\x2e\x68\x00\x01\x00\x00\x69\x6e\x74\x2d\x6c\x6c\x36\x34\x2e\x68\x00\x03\x00\x00\x62\x70\x66\x2e\x68\x00\x04\x00\x00\x69\x66\x5f\x65\x74\x68\x65\x72\x2e\x68\x00\x04\x00\x00\x74\x79\x70\x65\x73\x2e\x68\x00\x04\x00\x00\x69\x70\x2e\x68\x00\x04\x00\x00\x69\x70\x76\x36\x2e\x68\x00\x04\x00\x00\x69\x6e\x36\x2e\x68\x00\x04\x00\x00\x00\x04\x02\x00\x09\x02\x00\x00\x00\x00\x00\x00\x00\x00\x03\x27\x01\x05\x1d\x0a\x22\x05\x10\x06\x20\x03\x56\x20\x05\x0c\x06\x03\x2e\x2e\x06\x03\x52\x4a\x05\x06\x06\x03\x2f\x20\x05\x25\x25\x05\x21\x1f\x05\x11\x24\x05\x06\x06\x2e\x05\x17\x06\x1f\x05\x07\x4c\x05\x12\x30\x05\x08\x06\x2e\x05\x0d\x06\x21\x05\x19\x06\x20\x05\x09\x3c\x05\x0a\x06\x21\x06\x20\x03\x44\x20\x05\x12\x06\x03\xc2\x00\x20\x05\x08\x06\x2e\x05\x0d\x06\x21\x05\x18\x06\x20\x05\x09\x3c\x05\x0a\x06\x21\x06\x20\x05\x00\x03\xbc\x7f\x20\x05\x01\x06\x03\xcc\x00\x58\x02\x01\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb3\x04\x00\xff\xf1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x27\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x2c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x39\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x4d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x59\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x63\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x6f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x7b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x9e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\xc6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\xd7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x4e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x52\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x56\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x5b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x64\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x6e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x7e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x8d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x94\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\x9a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xa6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xad\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xb6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xbe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xd3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xda\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xe1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xe4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xe8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xed\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xf5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x01\xf9\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x3b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x4a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x53\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x5f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x67\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x71\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x77\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x94\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x9d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x01\x58\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfa\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf3\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x01\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe4\x01\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x03\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x11\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x3b\x11\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x64\x12\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x88\x00\x00\x00\x32\x11\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x28\x00\x00\x00\x57\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xd0\x00\x00\x00\x52\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x28\x00\x00\x00\x52\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x60\x00\x00\x00\x59\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x54\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x02\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x03\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x55\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00\x04\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x51\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x2b\x00\x00\x00\x05\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x37\x00\x00\x00\x59\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x0c\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x48\x00\x00\x00\x06\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x54\x00\x00\x00\x08\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x60\x00\x00\x00\x09\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x6c\x00\x00\x00\x0a\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x78\x00\x00\x00\x0b\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x07\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x8c\x00\x00\x00\x0d\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x98\x00\x00\x00\x57\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xa1\x00\x00\x00\x0e\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\xad\x00\x00\x00\x56\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xc2\x00\x00\x00\x0f\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\xc9\x00\x00\x00\x10\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\xd0\x00\x00\x00\x11\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\xf7\x00\x00\x00\x12\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00\x52\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x16\x00\x00\x00\x13\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x1d\x00\x00\x00\x14\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x43\x00\x00\x00\x15\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x4e\x00\x00\x00\x16\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x59\x00\x00\x00\x18\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x60\x00\x00\x00\x17\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x6b\x00\x00\x00\x1e\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x74\x00\x00\x00\x19\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x7a\x00\x00\x00\x1a\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x1b\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x86\x00\x00\x00\x1c\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x8c\x00\x00\x00\x1d\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\x93\x00\x00\x00\x51\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\xa1\x00\x00\x00\x1f\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xac\x00\x00\x00\x53\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xb0\x00\x00\x00\x21\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xbb\x00\x00\x00\x53\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xbf\x00\x00\x00\x28\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xca\x00\x00\x00\x53\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xce\x00\x00\x00\x29\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xd9\x00\x00\x00\x22\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xe4\x00\x00\x00\x53\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xe8\x00\x00\x00\x2a\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xf3\x00\x00\x00\x53\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xf7\x00\x00\x00\x23\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x02\x00\x00\x00\x53\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x06\x00\x00\x00\x2d\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x11\x00\x00\x00\x51\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x1e\x00\x00\x00\x53\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x22\x00\x00\x00\x32\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x2e\x00\x00\x00\x51\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x3b\x00\x00\x00\x53\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x3f\x00\x00\x00\x32\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x4c\x00\x00\x00\x20\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x58\x00\x00\x00\x27\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x61\x00\x00\x00\x22\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x6e\x00\x00\x00\x23\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x7b\x00\x00\x00\x24\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x88\x00\x00\x00\x25\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\x95\x00\x00\x00\x26\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\xad\x00\x00\x00\x31\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\xb5\x00\x00\x00\x2b\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\xc1\x00\x00\x00\x2c\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\xcd\x00\x00\x00\x2d\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\xea\x00\x00\x00\x30\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\xf5\x00\x00\x00\x2f\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x02\xfc\x00\x00\x00\x2e\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x08\x00\x00\x00\x41\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x10\x00\x00\x00\x33\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x1f\x00\x00\x00\x35\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x2e\x00\x00\x00\x36\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x3a\x00\x00\x00\x37\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x46\x00\x00\x00\x38\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x52\x00\x00\x00\x39\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x5e\x00\x00\x00\x3a\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x6a\x00\x00\x00\x3b\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x76\x00\x00\x00\x3c\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x82\x00\x00\x00\x3e\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x8e\x00\x00\x00\x40\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\x9f\x00\x00\x00\x34\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\xaa\x00\x00\x00\x3d\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\xb5\x00\x00\x00\x3f\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\xc1\x00\x00\x00\x4c\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\xc9\x00\x00\x00\x42\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\xd8\x00\x00\x00\x35\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\xe7\x00\x00\x00\x43\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\xf3\x00\x00\x00\x44\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x03\xff\x00\x00\x00\x45\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x04\x0b\x00\x00\x00\x46\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x04\x17\x00\x00\x00\x3e\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x04\x23\x00\x00\x00\x40\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x04\x3c\x00\x00\x00\x4b\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x04\x44\x00\x00\x00\x47\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x04\x54\x00\x00\x00\x48\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x04\x60\x00\x00\x00\x49\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x04\x6c\x00\x00\x00\x4a\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xb0\x00\x00\x00\x52\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x01\xc8\x00\x00\x00\x56\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe0\x00\x00\x00\x59\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xec\x00\x00\x00\x57\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2c\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x50\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x10\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x20\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x30\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x40\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x50\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x60\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x70\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x90\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xa0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xb0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xd0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xf0\x00\x00\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x51\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xec\x00\x00\x00\x51\x00\x00\x00\x01\x58\x59\x57\x50\x56\x00\x2e\x64\x65\x62\x75\x67\x5f\x61\x62\x62\x72\x65\x76\x00\x2e\x74\x65\x78\x74\x00\x2e\x72\x65\x6c\x2e\x42\x54\x46\x2e\x65\x78\x74\x00\x6d\x61\x70\x73\x00\x2e\x64\x65\x62\x75\x67\x5f\x73\x74\x72\x00\x78\x73\x6b\x73\x5f\x6d\x61\x70\x00\x71\x69\x64\x63\x6f\x6e\x66\x5f\x6d\x61\x70\x00\x2e\x72\x65\x6c\x2e\x64\x65\x62\x75\x67\x5f\x69\x6e\x66\x6f\x00\x2e\x72\x65\x6c\x78\x64\x70\x5f\x73\x6f\x63\x6b\x00\x78\x64\x70\x5f\x73\x6f\x63\x6b\x5f\x70\x72\x6f\x67\x00\x2e\x6c\x6c\x76\x6d\x5f\x61\x64\x64\x72\x73\x69\x67\x00\x5f\x5f\x6c\x69\x63\x65\x6e\x73\x65\x00\x2e\x72\x65\x6c\x2e\x64\x65\x62\x75\x67\x5f\x6c\x69\x6e\x65\x00\x2e\x72\x65\x6c\x2e\x65\x68\x5f\x66\x72\x61\x6d\x65\x00\x2e\x64\x65\x62\x75\x67\x5f\x6c\x6f\x63\x00\x73\x69\x6e\x67\x6c\x65\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x5f\x66\x69\x6c\x74\x65\x72\x2e\x63\x00\x2e\x73\x74\x72\x74\x61\x62\x00\x2e\x73\x79\x6d\x74\x61\x62\x00\x2e\x72\x6f\x64\x61\x74\x61\x00\x50\x52\x4f\x54\x4f\x00\x2e\x72\x65\x6c\x2e\x42\x54\x46\x00\x4c\x42\x42\x30\x5f\x38\x00\x4c\x42\x42\x30\x5f\x31\x32\x00\x4c\x42\x42\x30\x5f\x31\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcc\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x26\x35\x00\x00\x00\x00\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5b\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x01\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x57\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x80\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x16\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x22\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc8\x00\x00\x00\x00\x00\x00\x00\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdc\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xf1\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x27\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x0a\x00\x00\x00\x00\x00\x00\x02\xa5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa8\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\xaf\x00\x00\x00\x00\x00\x00\x01\xa3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x52\x00\x00\x00\x00\x00\x00\x01\x6e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4b\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xc0\x00\x00\x00\x00\x00\x00\x04\x9e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x47\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\xc0\x00\x00\x00\x00\x00\x00\x06\x40\x00\x00\x00\x16\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\xee\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x5e\x00\x00\x00\x00\x00\x00\x05\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xea\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x24\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x16\x00\x00\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x19\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x70\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x24\x40\x00\x00\x00\x00\x00\x00\x01\xd0\x00\x00\x00\x16\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x9e\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x70\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9a\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x26\x10\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x16\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x8e\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\xa0\x00\x00\x00\x00\x00\x00\x01\x6f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8a\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x26\x20\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x16\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x72\x6f\xff\x4c\x03\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x26\x30\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x10\x00\x00\x00\x00\x00\x00\x08\x70\x00\x00\x00\x01\x00\x00\x00\x56\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x18") 120 | -------------------------------------------------------------------------------- /examples/dumpframes/ebpf/ipproto_bpfel.go: -------------------------------------------------------------------------------- 1 | // Code generated by bpf2go; DO NOT EDIT. 2 | // +build 386 amd64 amd64p32 arm arm64 mipsle mips64le mips64p32le ppc64le riscv64 3 | 4 | package ebpf 5 | 6 | import ( 7 | "bytes" 8 | "fmt" 9 | "io" 10 | 11 | "github.com/cilium/ebpf" 12 | ) 13 | 14 | // loadIpproto returns the embedded CollectionSpec for ipproto. 15 | func loadIpproto() (*ebpf.CollectionSpec, error) { 16 | reader := bytes.NewReader(_IpprotoBytes) 17 | spec, err := ebpf.LoadCollectionSpecFromReader(reader) 18 | if err != nil { 19 | return nil, fmt.Errorf("can't load ipproto: %w", err) 20 | } 21 | 22 | return spec, err 23 | } 24 | 25 | // loadIpprotoObjects loads ipproto and converts it into a struct. 26 | // 27 | // The following types are suitable as obj argument: 28 | // 29 | // *ipprotoObjects 30 | // *ipprotoPrograms 31 | // *ipprotoMaps 32 | // 33 | // See ebpf.CollectionSpec.LoadAndAssign documentation for details. 34 | func loadIpprotoObjects(obj interface{}, opts *ebpf.CollectionOptions) error { 35 | spec, err := loadIpproto() 36 | if err != nil { 37 | return err 38 | } 39 | 40 | return spec.LoadAndAssign(obj, opts) 41 | } 42 | 43 | // ipprotoSpecs contains maps and programs before they are loaded into the kernel. 44 | // 45 | // It can be passed ebpf.CollectionSpec.Assign. 46 | type ipprotoSpecs struct { 47 | ipprotoProgramSpecs 48 | ipprotoMapSpecs 49 | } 50 | 51 | // ipprotoSpecs contains programs before they are loaded into the kernel. 52 | // 53 | // It can be passed ebpf.CollectionSpec.Assign. 54 | type ipprotoProgramSpecs struct { 55 | XdpSockProg *ebpf.ProgramSpec `ebpf:"xdp_sock_prog"` 56 | } 57 | 58 | // ipprotoMapSpecs contains maps before they are loaded into the kernel. 59 | // 60 | // It can be passed ebpf.CollectionSpec.Assign. 61 | type ipprotoMapSpecs struct { 62 | QidconfMap *ebpf.MapSpec `ebpf:"qidconf_map"` 63 | XsksMap *ebpf.MapSpec `ebpf:"xsks_map"` 64 | } 65 | 66 | // ipprotoObjects contains all objects after they have been loaded into the kernel. 67 | // 68 | // It can be passed to loadIpprotoObjects or ebpf.CollectionSpec.LoadAndAssign. 69 | type ipprotoObjects struct { 70 | ipprotoPrograms 71 | ipprotoMaps 72 | } 73 | 74 | func (o *ipprotoObjects) Close() error { 75 | return _IpprotoClose( 76 | &o.ipprotoPrograms, 77 | &o.ipprotoMaps, 78 | ) 79 | } 80 | 81 | // ipprotoMaps contains all maps after they have been loaded into the kernel. 82 | // 83 | // It can be passed to loadIpprotoObjects or ebpf.CollectionSpec.LoadAndAssign. 84 | type ipprotoMaps struct { 85 | QidconfMap *ebpf.Map `ebpf:"qidconf_map"` 86 | XsksMap *ebpf.Map `ebpf:"xsks_map"` 87 | } 88 | 89 | func (m *ipprotoMaps) Close() error { 90 | return _IpprotoClose( 91 | m.QidconfMap, 92 | m.XsksMap, 93 | ) 94 | } 95 | 96 | // ipprotoPrograms contains all programs after they have been loaded into the kernel. 97 | // 98 | // It can be passed to loadIpprotoObjects or ebpf.CollectionSpec.LoadAndAssign. 99 | type ipprotoPrograms struct { 100 | XdpSockProg *ebpf.Program `ebpf:"xdp_sock_prog"` 101 | } 102 | 103 | func (p *ipprotoPrograms) Close() error { 104 | return _IpprotoClose( 105 | p.XdpSockProg, 106 | ) 107 | } 108 | 109 | func _IpprotoClose(closers ...io.Closer) error { 110 | for _, closer := range closers { 111 | if err := closer.Close(); err != nil { 112 | return err 113 | } 114 | } 115 | return nil 116 | } 117 | 118 | // Do not access this directly. 119 | var _IpprotoBytes = []byte("\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\xf7\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x27\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x40\x00\x17\x00\x01\x00\xbf\x16\x00\x00\x00\x00\x00\x00\x61\x61\x10\x00\x00\x00\x00\x00\x63\x1a\xfc\xff\x00\x00\x00\x00\xbf\xa2\x00\x00\x00\x00\x00\x00\x07\x02\x00\x00\xfc\xff\xff\xff\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x01\x00\x00\x00\xbf\x01\x00\x00\x00\x00\x00\x00\xb7\x00\x00\x00\x02\x00\x00\x00\x15\x01\x26\x00\x00\x00\x00\x00\x61\x63\x04\x00\x00\x00\x00\x00\x61\x62\x00\x00\x00\x00\x00\x00\xbf\x24\x00\x00\x00\x00\x00\x00\x07\x04\x00\x00\x0e\x00\x00\x00\x2d\x34\x21\x00\x00\x00\x00\x00\x71\x25\x0c\x00\x00\x00\x00\x00\x71\x24\x0d\x00\x00\x00\x00\x00\x67\x04\x00\x00\x08\x00\x00\x00\x4f\x54\x00\x00\x00\x00\x00\x00\xdc\x04\x00\x00\x10\x00\x00\x00\x15\x04\x0c\x00\xdd\x86\x00\x00\x55\x04\x1a\x00\x00\x08\x00\x00\xbf\x24\x00\x00\x00\x00\x00\x00\x07\x04\x00\x00\x22\x00\x00\x00\x2d\x34\x17\x00\x00\x00\x00\x00\x71\x22\x17\x00\x00\x00\x00\x00\x18\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x71\x33\x00\x00\x00\x00\x00\x00\x5d\x32\x12\x00\x00\x00\x00\x00\x61\x11\x00\x00\x00\x00\x00\x00\x15\x01\x10\x00\x00\x00\x00\x00\x05\x00\x0a\x00\x00\x00\x00\x00\xbf\x24\x00\x00\x00\x00\x00\x00\x07\x04\x00\x00\x36\x00\x00\x00\x2d\x34\x0c\x00\x00\x00\x00\x00\x71\x22\x14\x00\x00\x00\x00\x00\x18\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x71\x33\x00\x00\x00\x00\x00\x00\x5d\x32\x07\x00\x00\x00\x00\x00\x61\x11\x00\x00\x00\x00\x00\x00\x15\x01\x05\x00\x00\x00\x00\x00\x61\xa2\xfc\xff\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb7\x03\x00\x00\x00\x00\x00\x00\x85\x00\x00\x00\x33\x00\x00\x00\x95\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x01\x4c\x47\x50\x4c\x2d\x32\x2e\x31\x20\x6f\x72\x20\x42\x53\x44\x2d\x32\x2d\x43\x6c\x61\x75\x73\x65\x00\x00\x2e\x2f\x73\x69\x6e\x67\x6c\x65\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x5f\x66\x69\x6c\x74\x65\x72\x2e\x63\x00\x2e\x00\x78\x73\x6b\x73\x5f\x6d\x61\x70\x00\x74\x79\x70\x65\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\x00\x6b\x65\x79\x5f\x73\x69\x7a\x65\x00\x76\x61\x6c\x75\x65\x5f\x73\x69\x7a\x65\x00\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x65\x73\x00\x6d\x61\x70\x5f\x66\x6c\x61\x67\x73\x00\x62\x70\x66\x5f\x6d\x61\x70\x5f\x64\x65\x66\x00\x71\x69\x64\x63\x6f\x6e\x66\x5f\x6d\x61\x70\x00\x5f\x5f\x6c\x69\x63\x65\x6e\x73\x65\x00\x63\x68\x61\x72\x00\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\x00\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x00\x50\x52\x4f\x54\x4f\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\x00\x62\x70\x66\x5f\x72\x65\x64\x69\x72\x65\x63\x74\x5f\x6d\x61\x70\x00\x6c\x6f\x6e\x67\x20\x69\x6e\x74\x00\x5f\x5f\x75\x33\x32\x00\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\x20\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\x00\x5f\x5f\x75\x36\x34\x00\x58\x44\x50\x5f\x41\x42\x4f\x52\x54\x45\x44\x00\x58\x44\x50\x5f\x44\x52\x4f\x50\x00\x58\x44\x50\x5f\x50\x41\x53\x53\x00\x58\x44\x50\x5f\x54\x58\x00\x58\x44\x50\x5f\x52\x45\x44\x49\x52\x45\x43\x54\x00\x78\x64\x70\x5f\x61\x63\x74\x69\x6f\x6e\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x73\x68\x6f\x72\x74\x00\x5f\x5f\x75\x31\x36\x00\x78\x64\x70\x5f\x73\x6f\x63\x6b\x5f\x70\x72\x6f\x67\x00\x69\x6e\x74\x00\x63\x74\x78\x00\x64\x61\x74\x61\x00\x64\x61\x74\x61\x5f\x65\x6e\x64\x00\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\x00\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\x65\x78\x00\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x69\x6e\x64\x65\x78\x00\x78\x64\x70\x5f\x6d\x64\x00\x69\x6e\x64\x65\x78\x00\x71\x69\x64\x63\x6f\x6e\x66\x00\x65\x74\x68\x00\x68\x5f\x64\x65\x73\x74\x00\x68\x5f\x73\x6f\x75\x72\x63\x65\x00\x68\x5f\x70\x72\x6f\x74\x6f\x00\x5f\x5f\x62\x65\x31\x36\x00\x65\x74\x68\x68\x64\x72\x00\x69\x70\x00\x69\x68\x6c\x00\x5f\x5f\x75\x38\x00\x76\x65\x72\x73\x69\x6f\x6e\x00\x74\x6f\x73\x00\x74\x6f\x74\x5f\x6c\x65\x6e\x00\x69\x64\x00\x66\x72\x61\x67\x5f\x6f\x66\x66\x00\x74\x74\x6c\x00\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x00\x63\x68\x65\x63\x6b\x00\x5f\x5f\x73\x75\x6d\x31\x36\x00\x73\x61\x64\x64\x72\x00\x5f\x5f\x62\x65\x33\x32\x00\x64\x61\x64\x64\x72\x00\x69\x70\x68\x64\x72\x00\x70\x72\x69\x6f\x72\x69\x74\x79\x00\x66\x6c\x6f\x77\x5f\x6c\x62\x6c\x00\x70\x61\x79\x6c\x6f\x61\x64\x5f\x6c\x65\x6e\x00\x6e\x65\x78\x74\x68\x64\x72\x00\x68\x6f\x70\x5f\x6c\x69\x6d\x69\x74\x00\x69\x6e\x36\x5f\x75\x00\x75\x36\x5f\x61\x64\x64\x72\x38\x00\x75\x36\x5f\x61\x64\x64\x72\x31\x36\x00\x75\x36\x5f\x61\x64\x64\x72\x33\x32\x00\x69\x6e\x36\x5f\x61\x64\x64\x72\x00\x69\x70\x76\x36\x68\x64\x72\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00\x51\x08\x00\x00\x00\x00\x00\x00\x00\x90\x01\x00\x00\x00\x00\x00\x00\x01\x00\x56\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x01\x00\x51\x18\x00\x00\x00\x00\x00\x00\x00\x60\x01\x00\x00\x00\x00\x00\x00\x02\x00\x7a\x04\x88\x01\x00\x00\x00\x00\x00\x00\x90\x01\x00\x00\x00\x00\x00\x00\x02\x00\x7a\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x48\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x51\x10\x01\x00\x00\x00\x00\x00\x00\x58\x01\x00\x00\x00\x00\x00\x00\x01\x00\x51\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x00\x00\x00\x00\x01\x00\x52\x10\x01\x00\x00\x00\x00\x00\x00\x30\x01\x00\x00\x00\x00\x00\x00\x01\x00\x52\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x00\x00\x00\x00\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x00\x00\x01\x00\x53\x10\x01\x00\x00\x00\x00\x00\x00\x40\x01\x00\x00\x00\x00\x00\x00\x01\x00\x53\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\xa8\x00\x00\x00\x00\x00\x00\x00\x01\x00\x54\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x00\x00\x00\x00\x03\x00\x72\x0e\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x01\x00\x00\x00\x00\x00\x00\x30\x01\x00\x00\x00\x00\x00\x00\x03\x00\x72\x0e\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x11\x01\x25\x0e\x13\x05\x03\x0e\x10\x17\x1b\x0e\x11\x01\x12\x06\x00\x00\x02\x34\x00\x03\x0e\x49\x13\x3f\x19\x3a\x0b\x3b\x0b\x02\x18\x00\x00\x03\x13\x01\x03\x0e\x0b\x0b\x3a\x0b\x3b\x0b\x00\x00\x04\x0d\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x0b\x38\x0b\x00\x00\x05\x24\x00\x03\x0e\x3e\x0b\x0b\x0b\x00\x00\x06\x01\x01\x49\x13\x00\x00\x07\x21\x00\x49\x13\x37\x0b\x00\x00\x08\x24\x00\x03\x0e\x0b\x0b\x3e\x0b\x00\x00\x09\x34\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x0b\x00\x00\x0a\x0f\x00\x49\x13\x00\x00\x0b\x15\x01\x49\x13\x27\x19\x00\x00\x0c\x05\x00\x49\x13\x00\x00\x0d\x0f\x00\x00\x00\x0e\x26\x00\x00\x00\x0f\x34\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x0b\x02\x18\x00\x00\x10\x26\x00\x49\x13\x00\x00\x11\x35\x00\x49\x13\x00\x00\x12\x34\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x05\x00\x00\x13\x16\x00\x49\x13\x03\x0e\x3a\x0b\x3b\x0b\x00\x00\x14\x04\x01\x49\x13\x03\x0e\x0b\x0b\x3a\x0b\x3b\x05\x00\x00\x15\x28\x00\x03\x0e\x1c\x0f\x00\x00\x16\x2e\x01\x11\x01\x12\x06\x40\x18\x97\x42\x19\x03\x0e\x3a\x0b\x3b\x0b\x27\x19\x49\x13\x3f\x19\x00\x00\x17\x05\x00\x02\x17\x03\x0e\x3a\x0b\x3b\x0b\x49\x13\x00\x00\x18\x34\x00\x02\x17\x03\x0e\x3a\x0b\x3b\x0b\x49\x13\x00\x00\x19\x34\x00\x03\x0e\x3a\x0b\x3b\x0b\x49\x13\x00\x00\x1a\x0b\x01\x11\x01\x12\x06\x00\x00\x1b\x13\x01\x03\x0e\x0b\x0b\x3a\x0b\x3b\x05\x00\x00\x1c\x0d\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x05\x38\x0b\x00\x00\x1d\x0d\x00\x03\x0e\x49\x13\x3a\x0b\x3b\x0b\x0b\x0b\x0d\x0b\x0c\x0b\x38\x0b\x00\x00\x1e\x17\x01\x0b\x0b\x3a\x0b\x3b\x0b\x00\x00\x00\x9a\x04\x00\x00\x04\x00\x00\x00\x00\x00\x08\x01\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x01\x00\x00\x02\x00\x00\x00\x00\x3f\x00\x00\x00\x02\x18\x09\x03\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x14\x01\x39\x04\x00\x00\x00\x00\x84\x00\x00\x00\x01\x3a\x00\x04\x00\x00\x00\x00\x84\x00\x00\x00\x01\x3b\x04\x04\x00\x00\x00\x00\x84\x00\x00\x00\x01\x3c\x08\x04\x00\x00\x00\x00\x84\x00\x00\x00\x01\x3d\x0c\x04\x00\x00\x00\x00\x84\x00\x00\x00\x01\x3e\x10\x00\x05\x00\x00\x00\x00\x07\x04\x02\x00\x00\x00\x00\x3f\x00\x00\x00\x02\x1f\x09\x03\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\xb5\x00\x00\x00\x02\x4f\x09\x03\x00\x00\x00\x00\x00\x00\x00\x00\x06\xc1\x00\x00\x00\x07\xc8\x00\x00\x00\x19\x00\x05\x00\x00\x00\x00\x06\x01\x08\x00\x00\x00\x00\x08\x07\x09\x00\x00\x00\x00\xda\x00\x00\x00\x03\x2a\x0a\xdf\x00\x00\x00\x0b\xef\x00\x00\x00\x0c\xef\x00\x00\x00\x0c\xf0\x00\x00\x00\x00\x0d\x0a\xf5\x00\x00\x00\x0e\x0f\x00\x00\x00\x00\x0b\x01\x00\x00\x02\x10\x09\x03\x00\x00\x00\x00\x00\x00\x00\x00\x10\x10\x01\x00\x00\x11\x15\x01\x00\x00\x05\x00\x00\x00\x00\x08\x01\x12\x00\x00\x00\x00\x28\x01\x00\x00\x03\xff\x04\x0a\x2d\x01\x00\x00\x0b\x42\x01\x00\x00\x0c\xef\x00\x00\x00\x0c\x49\x01\x00\x00\x0c\x54\x01\x00\x00\x00\x05\x00\x00\x00\x00\x05\x08\x13\x84\x00\x00\x00\x00\x00\x00\x00\x04\x1b\x13\x5f\x01\x00\x00\x00\x00\x00\x00\x04\x1f\x05\x00\x00\x00\x00\x07\x08\x14\x84\x00\x00\x00\x00\x00\x00\x00\x04\x05\xa1\x0d\x15\x00\x00\x00\x00\x00\x15\x00\x00\x00\x00\x01\x15\x00\x00\x00\x00\x02\x15\x00\x00\x00\x00\x03\x15\x00\x00\x00\x00\x04\x00\x13\x9d\x01\x00\x00\x00\x00\x00\x00\x04\x18\x05\x00\x00\x00\x00\x07\x02\x16\x00\x00\x00\x00\x00\x00\x00\x00\x90\x01\x00\x00\x01\x5a\x00\x00\x00\x00\x02\x27\x5d\x02\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00\x00\x02\x27\x64\x02\x00\x00\x18\x36\x00\x00\x00\x00\x00\x00\x00\x02\x2a\x5d\x02\x00\x00\x18\x81\x00\x00\x00\x00\x00\x00\x00\x02\x2a\xb4\x02\x00\x00\x19\x00\x00\x00\x00\x02\x33\xef\x00\x00\x00\x18\xb7\x00\x00\x00\x00\x00\x00\x00\x02\x35\xb9\x02\x00\x00\x18\xed\x00\x00\x00\x00\x00\x00\x00\x02\x34\xef\x00\x00\x00\x18\x23\x01\x00\x00\x00\x00\x00\x00\x02\x36\x92\x01\x00\x00\x1a\xb8\x00\x00\x00\x00\x00\x00\x00\x50\x00\x00\x00\x18\x46\x01\x00\x00\x00\x00\x00\x00\x02\x39\x02\x03\x00\x00\x00\x1a\x10\x01\x00\x00\x00\x00\x00\x00\x50\x00\x00\x00\x18\x6b\x01\x00\x00\x00\x00\x00\x00\x02\x41\xbb\x03\x00\x00\x00\x00\x05\x00\x00\x00\x00\x05\x04\x0a\x69\x02\x00\x00\x1b\x00\x00\x00\x00\x14\x05\xac\x0d\x1c\x00\x00\x00\x00\x49\x01\x00\x00\x05\xad\x0d\x00\x1c\x00\x00\x00\x00\x49\x01\x00\x00\x05\xae\x0d\x04\x1c\x00\x00\x00\x00\x49\x01\x00\x00\x05\xaf\x0d\x08\x1c\x00\x00\x00\x00\x49\x01\x00\x00\x05\xb1\x0d\x0c\x1c\x00\x00\x00\x00\x49\x01\x00\x00\x05\xb2\x0d\x10\x00\x0a\x5d\x02\x00\x00\x0a\xbe\x02\x00\x00\x03\x00\x00\x00\x00\x0e\x06\xa2\x04\x00\x00\x00\x00\xeb\x02\x00\x00\x06\xa3\x00\x04\x00\x00\x00\x00\xeb\x02\x00\x00\x06\xa4\x06\x04\x00\x00\x00\x00\xf7\x02\x00\x00\x06\xa5\x0c\x00\x06\x15\x01\x00\x00\x07\xc8\x00\x00\x00\x06\x00\x13\x92\x01\x00\x00\x00\x00\x00\x00\x07\x19\x0a\x07\x03\x00\x00\x03\x00\x00\x00\x00\x14\x08\x56\x1d\x00\x00\x00\x00\x9a\x03\x00\x00\x08\x58\x01\x04\x04\x00\x1d\x00\x00\x00\x00\x9a\x03\x00\x00\x08\x59\x01\x04\x00\x00\x04\x00\x00\x00\x00\x9a\x03\x00\x00\x08\x60\x01\x04\x00\x00\x00\x00\xf7\x02\x00\x00\x08\x61\x02\x04\x00\x00\x00\x00\xf7\x02\x00\x00\x08\x62\x04\x04\x00\x00\x00\x00\xf7\x02\x00\x00\x08\x63\x06\x04\x00\x00\x00\x00\x9a\x03\x00\x00\x08\x64\x08\x04\x00\x00\x00\x00\x9a\x03\x00\x00\x08\x65\x09\x04\x00\x00\x00\x00\xa5\x03\x00\x00\x08\x66\x0a\x04\x00\x00\x00\x00\xb0\x03\x00\x00\x08\x67\x0c\x04\x00\x00\x00\x00\xb0\x03\x00\x00\x08\x68\x10\x00\x13\x15\x01\x00\x00\x00\x00\x00\x00\x04\x15\x13\x92\x01\x00\x00\x00\x00\x00\x00\x07\x1f\x13\x49\x01\x00\x00\x00\x00\x00\x00\x07\x1b\x0a\xc0\x03\x00\x00\x03\x00\x00\x00\x00\x28\x09\x74\x1d\x00\x00\x00\x00\x9a\x03\x00\x00\x09\x76\x01\x04\x04\x00\x1d\x00\x00\x00\x00\x9a\x03\x00\x00\x09\x77\x01\x04\x00\x00\x04\x00\x00\x00\x00\x2f\x04\x00\x00\x09\x7e\x01\x04\x00\x00\x00\x00\xf7\x02\x00\x00\x09\x80\x04\x04\x00\x00\x00\x00\x9a\x03\x00\x00\x09\x81\x06\x04\x00\x00\x00\x00\x9a\x03\x00\x00\x09\x82\x07\x04\x00\x00\x00\x00\x3b\x04\x00\x00\x09\x84\x08\x04\x00\x00\x00\x00\x3b\x04\x00\x00\x09\x85\x18\x00\x06\x9a\x03\x00\x00\x07\xc8\x00\x00\x00\x03\x00\x03\x00\x00\x00\x00\x10\x0a\x21\x04\x00\x00\x00\x00\x4f\x04\x00\x00\x0a\x28\x00\x1e\x10\x0a\x22\x04\x00\x00\x00\x00\x79\x04\x00\x00\x0a\x23\x00\x04\x00\x00\x00\x00\x85\x04\x00\x00\x0a\x25\x00\x04\x00\x00\x00\x00\x91\x04\x00\x00\x0a\x26\x00\x00\x00\x06\x9a\x03\x00\x00\x07\xc8\x00\x00\x00\x10\x00\x06\xf7\x02\x00\x00\x07\xc8\x00\x00\x00\x08\x00\x06\xb0\x03\x00\x00\x07\xc8\x00\x00\x00\x04\x00\x00\x9f\xeb\x01\x00\x18\x00\x00\x00\x00\x00\x00\x00\xdc\x01\x00\x00\xdc\x01\x00\x00\x1e\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x02\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x04\x14\x00\x00\x00\x08\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x03\x00\x00\x00\x20\x00\x00\x00\x16\x00\x00\x00\x03\x00\x00\x00\x40\x00\x00\x00\x20\x00\x00\x00\x03\x00\x00\x00\x60\x00\x00\x00\x30\x00\x00\x00\x03\x00\x00\x00\x80\x00\x00\x00\x3f\x00\x00\x00\x00\x00\x00\x08\x04\x00\x00\x00\x45\x00\x00\x00\x00\x00\x00\x01\x04\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x0d\x06\x00\x00\x00\x52\x00\x00\x00\x01\x00\x00\x00\x56\x00\x00\x00\x00\x00\x00\x01\x04\x00\x00\x00\x20\x00\x00\x01\x5a\x00\x00\x00\x01\x00\x00\x0c\x05\x00\x00\x00\x82\x02\x00\x00\x05\x00\x00\x04\x14\x00\x00\x00\x8e\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x93\x02\x00\x00\x04\x00\x00\x00\x20\x00\x00\x00\x9c\x02\x00\x00\x04\x00\x00\x00\x40\x00\x00\x00\xa7\x02\x00\x00\x04\x00\x00\x00\x60\x00\x00\x00\xb3\x02\x00\x00\x04\x00\x00\x00\x80\x00\x00\x00\xbd\x02\x00\x00\x00\x00\x00\x0e\x08\x00\x00\x00\x01\x00\x00\x00\xc6\x02\x00\x00\x00\x00\x00\x0e\x08\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x0d\x00\x00\x00\xd2\x02\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x08\x00\x00\x00\xe0\x02\x00\x00\x00\x00\x00\x0e\x0b\x00\x00\x00\x00\x00\x00\x00\xe6\x02\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x08\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x0f\x00\x00\x00\x11\x00\x00\x00\x19\x00\x00\x00\xeb\x02\x00\x00\x00\x00\x00\x01\x04\x00\x00\x00\x20\x00\x00\x00\xff\x02\x00\x00\x00\x00\x00\x0e\x10\x00\x00\x00\x01\x00\x00\x00\x09\x03\x00\x00\x01\x00\x00\x0f\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x11\x03\x00\x00\x01\x00\x00\x0f\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x19\x03\x00\x00\x02\x00\x00\x0f\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x78\x64\x70\x5f\x6d\x64\x00\x64\x61\x74\x61\x00\x64\x61\x74\x61\x5f\x65\x6e\x64\x00\x64\x61\x74\x61\x5f\x6d\x65\x74\x61\x00\x69\x6e\x67\x72\x65\x73\x73\x5f\x69\x66\x69\x6e\x64\x65\x78\x00\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x69\x6e\x64\x65\x78\x00\x5f\x5f\x75\x33\x32\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\x74\x00\x63\x74\x78\x00\x69\x6e\x74\x00\x78\x64\x70\x5f\x73\x6f\x63\x6b\x5f\x70\x72\x6f\x67\x00\x78\x64\x70\x5f\x73\x6f\x63\x6b\x00\x2e\x2f\x2e\x2f\x73\x69\x6e\x67\x6c\x65\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x5f\x66\x69\x6c\x74\x65\x72\x2e\x63\x00\x53\x45\x43\x28\x22\x78\x64\x70\x5f\x73\x6f\x63\x6b\x22\x29\x20\x69\x6e\x74\x20\x78\x64\x70\x5f\x73\x6f\x63\x6b\x5f\x70\x72\x6f\x67\x28\x73\x74\x72\x75\x63\x74\x20\x78\x64\x70\x5f\x6d\x64\x20\x2a\x63\x74\x78\x29\x00\x09\x69\x6e\x74\x20\x2a\x71\x69\x64\x63\x6f\x6e\x66\x2c\x20\x69\x6e\x64\x65\x78\x20\x3d\x20\x63\x74\x78\x2d\x3e\x72\x78\x5f\x71\x75\x65\x75\x65\x5f\x69\x6e\x64\x65\x78\x3b\x00\x09\x71\x69\x64\x63\x6f\x6e\x66\x20\x3d\x20\x62\x70\x66\x5f\x6d\x61\x70\x5f\x6c\x6f\x6f\x6b\x75\x70\x5f\x65\x6c\x65\x6d\x28\x26\x71\x69\x64\x63\x6f\x6e\x66\x5f\x6d\x61\x70\x2c\x20\x26\x69\x6e\x64\x65\x78\x29\x3b\x00\x09\x69\x66\x20\x28\x21\x71\x69\x64\x63\x6f\x6e\x66\x29\x00\x09\x76\x6f\x69\x64\x20\x2a\x64\x61\x74\x61\x5f\x65\x6e\x64\x20\x3d\x20\x28\x76\x6f\x69\x64\x2a\x29\x28\x6c\x6f\x6e\x67\x29\x63\x74\x78\x2d\x3e\x64\x61\x74\x61\x5f\x65\x6e\x64\x3b\x00\x09\x76\x6f\x69\x64\x20\x2a\x64\x61\x74\x61\x20\x3d\x20\x28\x76\x6f\x69\x64\x2a\x29\x28\x6c\x6f\x6e\x67\x29\x63\x74\x78\x2d\x3e\x64\x61\x74\x61\x3b\x00\x09\x69\x66\x20\x28\x28\x76\x6f\x69\x64\x2a\x29\x65\x74\x68\x20\x2b\x20\x73\x69\x7a\x65\x6f\x66\x28\x2a\x65\x74\x68\x29\x20\x3c\x3d\x20\x64\x61\x74\x61\x5f\x65\x6e\x64\x29\x20\x7b\x00\x09\x5f\x5f\x75\x31\x36\x20\x68\x5f\x70\x72\x6f\x74\x6f\x20\x3d\x20\x65\x74\x68\x2d\x3e\x68\x5f\x70\x72\x6f\x74\x6f\x3b\x00\x09\x09\x69\x66\x20\x28\x62\x70\x66\x5f\x68\x74\x6f\x6e\x73\x28\x68\x5f\x70\x72\x6f\x74\x6f\x29\x20\x3d\x3d\x20\x45\x54\x48\x5f\x50\x5f\x49\x50\x29\x20\x7b\x00\x09\x09\x09\x69\x66\x20\x28\x28\x76\x6f\x69\x64\x2a\x29\x69\x70\x20\x2b\x20\x73\x69\x7a\x65\x6f\x66\x28\x2a\x69\x70\x29\x20\x3c\x3d\x20\x64\x61\x74\x61\x5f\x65\x6e\x64\x29\x20\x7b\x00\x09\x09\x09\x09\x69\x66\x20\x28\x69\x70\x2d\x3e\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x20\x3d\x3d\x20\x50\x52\x4f\x54\x4f\x29\x20\x7b\x00\x09\x09\x09\x09\x09\x69\x66\x20\x28\x2a\x71\x69\x64\x63\x6f\x6e\x66\x29\x00\x09\x09\x09\x09\x69\x66\x20\x28\x69\x70\x2d\x3e\x6e\x65\x78\x74\x68\x64\x72\x20\x3d\x3d\x20\x50\x52\x4f\x54\x4f\x29\x20\x7b\x00\x7d\x00\x62\x70\x66\x5f\x6d\x61\x70\x5f\x64\x65\x66\x00\x74\x79\x70\x65\x00\x6b\x65\x79\x5f\x73\x69\x7a\x65\x00\x76\x61\x6c\x75\x65\x5f\x73\x69\x7a\x65\x00\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x65\x73\x00\x6d\x61\x70\x5f\x66\x6c\x61\x67\x73\x00\x78\x73\x6b\x73\x5f\x6d\x61\x70\x00\x71\x69\x64\x63\x6f\x6e\x66\x5f\x6d\x61\x70\x00\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x63\x68\x61\x72\x00\x50\x52\x4f\x54\x4f\x00\x63\x68\x61\x72\x00\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\x00\x5f\x5f\x6c\x69\x63\x65\x6e\x73\x65\x00\x2e\x72\x6f\x64\x61\x74\x61\x00\x6c\x69\x63\x65\x6e\x73\x65\x00\x6d\x61\x70\x73\x00\x9f\xeb\x01\x00\x20\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x14\x00\x00\x00\xcc\x01\x00\x00\xe0\x01\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x68\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x68\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x71\x00\x00\x00\x8e\x00\x00\x00\x00\x9c\x00\x00\x08\x00\x00\x00\x71\x00\x00\x00\xc4\x00\x00\x00\x1d\xa8\x00\x00\x10\x00\x00\x00\x71\x00\x00\x00\xc4\x00\x00\x00\x10\xa8\x00\x00\x20\x00\x00\x00\x71\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x00\x00\x00\x71\x00\x00\x00\xf0\x00\x00\x00\x0c\xb8\x00\x00\x50\x00\x00\x00\x71\x00\x00\x00\x26\x01\x00\x00\x06\xbc\x00\x00\x58\x00\x00\x00\x71\x00\x00\x00\x35\x01\x00\x00\x25\xd0\x00\x00\x60\x00\x00\x00\x71\x00\x00\x00\x63\x01\x00\x00\x21\xcc\x00\x00\x68\x00\x00\x00\x71\x00\x00\x00\x89\x01\x00\x00\x11\xdc\x00\x00\x78\x00\x00\x00\x71\x00\x00\x00\x89\x01\x00\x00\x06\xdc\x00\x00\x80\x00\x00\x00\x71\x00\x00\x00\xb7\x01\x00\x00\x17\xd8\x00\x00\xa8\x00\x00\x00\x71\x00\x00\x00\xd6\x01\x00\x00\x07\xe0\x00\x00\xb8\x00\x00\x00\x71\x00\x00\x00\xfe\x01\x00\x00\x12\xe8\x00\x00\xc8\x00\x00\x00\x71\x00\x00\x00\xfe\x01\x00\x00\x08\xe8\x00\x00\xd0\x00\x00\x00\x71\x00\x00\x00\x2c\x02\x00\x00\x0d\xec\x00\x00\xd8\x00\x00\x00\x71\x00\x00\x00\x2c\x02\x00\x00\x19\xec\x00\x00\xf0\x00\x00\x00\x71\x00\x00\x00\x2c\x02\x00\x00\x09\xec\x00\x00\xf8\x00\x00\x00\x71\x00\x00\x00\x4d\x02\x00\x00\x0a\xf0\x00\x00\x00\x01\x00\x00\x71\x00\x00\x00\x4d\x02\x00\x00\x0a\xf0\x00\x00\x10\x01\x00\x00\x71\x00\x00\x00\xfe\x01\x00\x00\x12\x08\x01\x00\x20\x01\x00\x00\x71\x00\x00\x00\xfe\x01\x00\x00\x08\x08\x01\x00\x28\x01\x00\x00\x71\x00\x00\x00\x60\x02\x00\x00\x0d\x0c\x01\x00\x30\x01\x00\x00\x71\x00\x00\x00\x60\x02\x00\x00\x18\x0c\x01\x00\x48\x01\x00\x00\x71\x00\x00\x00\x60\x02\x00\x00\x09\x0c\x01\x00\x50\x01\x00\x00\x71\x00\x00\x00\x4d\x02\x00\x00\x0a\x10\x01\x00\x58\x01\x00\x00\x71\x00\x00\x00\x4d\x02\x00\x00\x0a\x10\x01\x00\x60\x01\x00\x00\x71\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\x01\x00\x00\x71\x00\x00\x00\x80\x02\x00\x00\x01\x30\x01\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x01\x7a\x52\x00\x08\x7c\x0b\x01\x0c\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x72\x01\x00\x00\x04\x00\xdd\x00\x00\x00\x08\x01\x01\xfb\x0e\x0d\x00\x01\x01\x01\x01\x00\x00\x00\x01\x00\x00\x01\x2e\x2f\x69\x6e\x63\x6c\x75\x64\x65\x2f\x62\x70\x66\x00\x2e\x00\x2f\x75\x73\x72\x2f\x69\x6e\x63\x6c\x75\x64\x65\x2f\x61\x73\x6d\x2d\x67\x65\x6e\x65\x72\x69\x63\x00\x2f\x75\x73\x72\x2f\x69\x6e\x63\x6c\x75\x64\x65\x2f\x6c\x69\x6e\x75\x78\x00\x00\x62\x70\x66\x5f\x68\x65\x6c\x70\x65\x72\x73\x2e\x68\x00\x01\x00\x00\x73\x69\x6e\x67\x6c\x65\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x5f\x66\x69\x6c\x74\x65\x72\x2e\x63\x00\x02\x00\x00\x62\x70\x66\x5f\x68\x65\x6c\x70\x65\x72\x5f\x64\x65\x66\x73\x2e\x68\x00\x01\x00\x00\x69\x6e\x74\x2d\x6c\x6c\x36\x34\x2e\x68\x00\x03\x00\x00\x62\x70\x66\x2e\x68\x00\x04\x00\x00\x69\x66\x5f\x65\x74\x68\x65\x72\x2e\x68\x00\x04\x00\x00\x74\x79\x70\x65\x73\x2e\x68\x00\x04\x00\x00\x69\x70\x2e\x68\x00\x04\x00\x00\x69\x70\x76\x36\x2e\x68\x00\x04\x00\x00\x69\x6e\x36\x2e\x68\x00\x04\x00\x00\x00\x04\x02\x00\x09\x02\x00\x00\x00\x00\x00\x00\x00\x00\x03\x27\x01\x05\x1d\x0a\x22\x05\x10\x06\x20\x03\x56\x20\x05\x0c\x06\x03\x2e\x2e\x06\x03\x52\x4a\x05\x06\x06\x03\x2f\x20\x05\x25\x25\x05\x21\x1f\x05\x11\x24\x05\x06\x06\x2e\x05\x17\x06\x1f\x06\x03\x4a\x4a\x05\x07\x06\x03\x38\x20\x05\x12\x30\x05\x08\x06\x2e\x05\x0d\x06\x21\x05\x19\x06\x20\x05\x09\x3c\x05\x0a\x06\x21\x06\x20\x03\x44\x20\x05\x12\x06\x03\xc2\x00\x20\x05\x08\x06\x2e\x05\x0d\x06\x21\x05\x18\x06\x20\x05\x09\x3c\x05\x0a\x06\x21\x06\x20\x05\x00\x03\xbc\x7f\x20\x05\x01\x06\x03\xcc\x00\x58\x02\x01\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb3\x00\x00\x00\x04\x00\xf1\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x27\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x2c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x39\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x4d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x59\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x63\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x6f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x7b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x85\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x8a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x9e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xb2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xc6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xd7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xe6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x03\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x0f\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x21\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x28\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x35\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x40\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x4f\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x55\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x63\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x67\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x6b\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x70\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x79\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x83\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x93\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xa2\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xa9\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xaf\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xb7\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xbb\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xc2\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xcb\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xd3\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xda\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xe1\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xe4\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xe8\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xed\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xf5\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\xf9\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x04\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x0d\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x11\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x1a\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x20\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x28\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x2e\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x35\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x3b\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x41\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x4a\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x53\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x5f\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x67\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x71\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x77\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x80\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x8a\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x94\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x9d\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x03\x00\x60\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfa\x00\x00\x00\x00\x00\x03\x00\x88\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf3\x00\x00\x00\x00\x00\x03\x00\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe4\x00\x00\x00\x01\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x11\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x3b\x00\x00\x00\x11\x00\x05\x00\x14\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x64\x00\x00\x00\x12\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x90\x01\x00\x00\x00\x00\x00\x00\x32\x00\x00\x00\x11\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x28\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x57\x00\x00\x00\xd8\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x52\x00\x00\x00\x30\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x52\x00\x00\x00\x68\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x59\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x54\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x02\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x03\x00\x00\x00\x16\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x55\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x04\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x51\x00\x00\x00\x2b\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x05\x00\x00\x00\x37\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x59\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0c\x00\x00\x00\x48\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x06\x00\x00\x00\x54\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x08\x00\x00\x00\x60\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x09\x00\x00\x00\x6c\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0a\x00\x00\x00\x78\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0b\x00\x00\x00\x85\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x07\x00\x00\x00\x8c\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0d\x00\x00\x00\x98\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x57\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0e\x00\x00\x00\xad\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x56\x00\x00\x00\xc2\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x0f\x00\x00\x00\xc9\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x10\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x11\x00\x00\x00\xf7\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x12\x00\x00\x00\x03\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x52\x00\x00\x00\x16\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x13\x00\x00\x00\x1d\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x14\x00\x00\x00\x43\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x15\x00\x00\x00\x4e\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x16\x00\x00\x00\x59\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x18\x00\x00\x00\x60\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x17\x00\x00\x00\x6b\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x1e\x00\x00\x00\x74\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x19\x00\x00\x00\x7a\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x1a\x00\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x1b\x00\x00\x00\x86\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x1c\x00\x00\x00\x8c\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x1d\x00\x00\x00\x97\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x20\x00\x00\x00\x9e\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x1f\x00\x00\x00\xa5\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x51\x00\x00\x00\xb3\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x21\x00\x00\x00\xbe\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x53\x00\x00\x00\xc2\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x23\x00\x00\x00\xcd\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x53\x00\x00\x00\xd1\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x2a\x00\x00\x00\xdc\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x53\x00\x00\x00\xe0\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x2b\x00\x00\x00\xeb\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x24\x00\x00\x00\xf6\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x53\x00\x00\x00\xfa\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x2c\x00\x00\x00\x05\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x53\x00\x00\x00\x09\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x25\x00\x00\x00\x14\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x53\x00\x00\x00\x18\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x2f\x00\x00\x00\x23\x02\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x51\x00\x00\x00\x30\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x53\x00\x00\x00\x34\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x32\x00\x00\x00\x40\x02\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x51\x00\x00\x00\x4d\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x53\x00\x00\x00\x51\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x32\x00\x00\x00\x5e\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x22\x00\x00\x00\x6a\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x29\x00\x00\x00\x73\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x24\x00\x00\x00\x80\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x25\x00\x00\x00\x8d\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x26\x00\x00\x00\x9a\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x27\x00\x00\x00\xa7\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x28\x00\x00\x00\xbf\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x31\x00\x00\x00\xc7\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x2d\x00\x00\x00\xd3\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x2e\x00\x00\x00\xdf\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x2f\x00\x00\x00\xfc\x02\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x30\x00\x00\x00\x08\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x41\x00\x00\x00\x10\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x33\x00\x00\x00\x1f\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x35\x00\x00\x00\x2e\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x36\x00\x00\x00\x3a\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x37\x00\x00\x00\x46\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x38\x00\x00\x00\x52\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x39\x00\x00\x00\x5e\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x3a\x00\x00\x00\x6a\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x3b\x00\x00\x00\x76\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x3c\x00\x00\x00\x82\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x3e\x00\x00\x00\x8e\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x40\x00\x00\x00\x9f\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x34\x00\x00\x00\xaa\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x3d\x00\x00\x00\xb5\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x3f\x00\x00\x00\xc1\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x4c\x00\x00\x00\xc9\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x42\x00\x00\x00\xd8\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x35\x00\x00\x00\xe7\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x43\x00\x00\x00\xf3\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x44\x00\x00\x00\xff\x03\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x45\x00\x00\x00\x0b\x04\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x46\x00\x00\x00\x17\x04\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x3e\x00\x00\x00\x23\x04\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x40\x00\x00\x00\x3c\x04\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x4b\x00\x00\x00\x44\x04\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x47\x00\x00\x00\x54\x04\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x48\x00\x00\x00\x60\x04\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x49\x00\x00\x00\x6c\x04\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x4a\x00\x00\x00\xb0\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x52\x00\x00\x00\xc8\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x56\x00\x00\x00\xe0\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x59\x00\x00\x00\xec\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x57\x00\x00\x00\x2c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x50\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x70\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x30\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x40\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x50\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x60\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x70\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x90\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xa0\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xb0\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xc0\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xd0\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xe0\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\xf0\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x51\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x51\x00\x00\x00\xec\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x51\x00\x00\x00\x58\x59\x57\x50\x56\x00\x2e\x64\x65\x62\x75\x67\x5f\x61\x62\x62\x72\x65\x76\x00\x2e\x74\x65\x78\x74\x00\x2e\x72\x65\x6c\x2e\x42\x54\x46\x2e\x65\x78\x74\x00\x6d\x61\x70\x73\x00\x2e\x64\x65\x62\x75\x67\x5f\x73\x74\x72\x00\x78\x73\x6b\x73\x5f\x6d\x61\x70\x00\x71\x69\x64\x63\x6f\x6e\x66\x5f\x6d\x61\x70\x00\x2e\x72\x65\x6c\x2e\x64\x65\x62\x75\x67\x5f\x69\x6e\x66\x6f\x00\x2e\x72\x65\x6c\x78\x64\x70\x5f\x73\x6f\x63\x6b\x00\x78\x64\x70\x5f\x73\x6f\x63\x6b\x5f\x70\x72\x6f\x67\x00\x2e\x6c\x6c\x76\x6d\x5f\x61\x64\x64\x72\x73\x69\x67\x00\x5f\x5f\x6c\x69\x63\x65\x6e\x73\x65\x00\x2e\x72\x65\x6c\x2e\x64\x65\x62\x75\x67\x5f\x6c\x69\x6e\x65\x00\x2e\x72\x65\x6c\x2e\x65\x68\x5f\x66\x72\x61\x6d\x65\x00\x2e\x64\x65\x62\x75\x67\x5f\x6c\x6f\x63\x00\x73\x69\x6e\x67\x6c\x65\x5f\x70\x72\x6f\x74\x6f\x63\x6f\x6c\x5f\x66\x69\x6c\x74\x65\x72\x2e\x63\x00\x2e\x73\x74\x72\x74\x61\x62\x00\x2e\x73\x79\x6d\x74\x61\x62\x00\x2e\x72\x6f\x64\x61\x74\x61\x00\x50\x52\x4f\x54\x4f\x00\x2e\x72\x65\x6c\x2e\x42\x54\x46\x00\x4c\x42\x42\x30\x5f\x38\x00\x4c\x42\x42\x30\x5f\x31\x32\x00\x4c\x42\x42\x30\x5f\x31\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcc\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x35\x26\x00\x00\x00\x00\x00\x00\x0a\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5b\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x90\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x57\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x1d\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x03\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x22\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd0\x01\x00\x00\x00\x00\x00\x00\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xdc\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf9\x01\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x27\x00\x00\x00\x01\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x02\x00\x00\x00\x00\x00\x00\xa5\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xa8\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb7\x04\x00\x00\x00\x00\x00\x00\x90\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x47\x06\x00\x00\x00\x00\x00\x00\x6e\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4b\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb5\x07\x00\x00\x00\x00\x00\x00\x9e\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x47\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x1d\x00\x00\x00\x00\x00\x00\x40\x06\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x0b\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\xee\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x53\x0c\x00\x00\x00\x00\x00\x00\x12\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xea\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x24\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x0d\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x65\x11\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x24\x00\x00\x00\x00\x00\x00\xd0\x01\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x0f\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x9e\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x13\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9a\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x26\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x11\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x8e\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\x13\x00\x00\x00\x00\x00\x00\x76\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8a\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x26\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x13\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x72\x00\x00\x00\x03\x4c\xff\x6f\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x26\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x15\x00\x00\x00\x00\x00\x00\x70\x08\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x56\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00") 120 | --------------------------------------------------------------------------------