├── .github ├── codeql │ └── codeql-config.yml ├── dependabot.yml └── workflows │ ├── ci.yml │ └── codeql-analysis.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── Vagrantfile ├── docs ├── README.md ├── development │ ├── glb-hashing.md │ ├── gue-header.md │ └── second-chance-design.md ├── images │ ├── ecmp-redist-break.png │ ├── ecmp-redist-glb.png │ ├── ecmp-redist-lvs-no-state.png │ ├── forwarding-table-active.png │ ├── forwarding-table-draining.png │ ├── forwarding-table-filling.png │ ├── forwarding-table-removed.png │ ├── glb-component-overview.png │ ├── glb-logo-dark.png │ ├── glb-proxy-state-machine.png │ ├── second-chance-nolegend.png │ └── second-chance.png └── setup │ ├── backend-proxy-setup.md │ ├── example-setup-vagrant.md │ ├── forwarding-table-config.md │ ├── glb-director-configuration.md │ ├── glb-healthcheck-configuration.md │ ├── images │ ├── flow-paths.png │ └── vagrant-setup.png │ ├── known-compatible-dpdk.md │ └── packages-quick-start.md ├── requirements.txt ├── script ├── Dockerfile.focal ├── Dockerfile.stretch ├── cibuild ├── cibuild-create-packages ├── cibuild-create-packages-focal ├── cibuild-prepare ├── helpers │ ├── configure-vagrant-director.sh │ ├── configure-vagrant-router.sh │ ├── configure-vagrant-user.sh │ ├── dkms.diff │ ├── folding.sh │ ├── prepare-vagrant │ ├── test-snoop.py │ └── test-snoop.service ├── test-glb-director ├── test-glb-director-xdp ├── test-glb-healthcheck └── test-glb-redirect └── src ├── glb-director-xdp ├── .gitignore ├── Makefile ├── bpf │ ├── Makefile │ ├── bpf_helper_defs.h │ ├── bpf_helpers.h │ ├── glb_encap.c │ ├── glb_encap_limits.h │ ├── glb_encap_trace.c │ ├── glb_stats.h │ ├── include │ │ └── asm │ │ │ └── barrier.h │ ├── passer.c │ ├── tailcall.c │ └── xdpcap_hook.h ├── go.mod ├── go.sum ├── main.go ├── packaging │ ├── after-upgrade-custom-systemd.sh │ ├── glb-director-xdp │ ├── glb-director-xdp.service │ ├── version.sh │ ├── xdp-root-shim │ └── xdp-root-shim@.service ├── script │ ├── create-packages │ └── test └── xdp-root-shim │ ├── Makefile │ └── xdp-root-shim.c ├── glb-director ├── .gitignore ├── Makefile ├── README.md ├── bind_classifier.c ├── bind_classifier.h ├── bind_classifier_rules.h ├── cli │ ├── .gitignore │ ├── Makefile │ ├── config_check.c │ ├── main.c │ ├── pcap_mode.c │ └── stub_server.c ├── cmdline_parse.c ├── cmdline_parse.h ├── cmdline_parse_etheraddr.c ├── cmdline_parse_etheraddr.h ├── config.h ├── glb_control_loop.c ├── glb_control_loop.h ├── glb_director_config.c ├── glb_director_config.h ├── glb_encap.c ├── glb_encap.h ├── glb_encap_dpdk.c ├── glb_encap_dpdk.h ├── glb_encap_pcap.c ├── glb_encap_pcap.h ├── glb_fwd_config.c ├── glb_fwd_config.h ├── glb_kni.c ├── glb_kni.h ├── glb_processor_loop.c ├── glb_processor_loop.h ├── log.h ├── main.c ├── packaging │ ├── .gitignore │ ├── director.conf │ ├── forwarding_table.json │ ├── glb-director │ ├── glb-director.service │ └── version.sh ├── script │ ├── create-packages │ └── test ├── shared_opt.c ├── shared_opt.h ├── siphash24.c ├── siphash24.h ├── statsd-client.c ├── statsd-client.h ├── strlcpy.h ├── tests │ ├── config_check.sh │ ├── data │ │ ├── 1k_pkts.pcap │ │ ├── config.json │ │ ├── dummy1.bin │ │ ├── table.json │ │ ├── table1.json │ │ ├── table2.json │ │ └── table3.json │ ├── glb_test_utils.py │ ├── lib │ │ └── testlib.sh │ ├── pcap_tests.sh │ ├── rendezvous_table.py │ ├── stub_server_tests.sh │ ├── test-config.json │ ├── test_cli_tool.py │ ├── test_director_classify_ranges_v4.py │ ├── test_director_classify_ranges_v6.py │ ├── test_director_classify_v4.py │ ├── test_director_classify_v6.py │ ├── test_director_hash_fields.py │ ├── test_director_kni.py │ ├── test_director_metrics.py │ ├── test_rendezvous_table.py │ └── valgrind_check.sh └── util.h ├── glb-hashing ├── glb_gue.h ├── glb_siphash24.h ├── packet_parsing.h └── pdnet.h ├── glb-healthcheck ├── .gitignore ├── GLBTable.go ├── HealthCheckManager.go ├── HealthChecker.go ├── HealthCheckerAppContext.go ├── HealthResultDampener.go ├── HealthResultDampener_test.go ├── HttpHealthChecker.go ├── Makefile ├── README.md ├── TcpHealthChecker.go ├── TunnelHealthChecker.go ├── go.mod ├── go.sum ├── main.go ├── packaging │ ├── forwarding_table.checked.json │ ├── forwarding_table.src.json │ ├── glb-healthcheck.service │ ├── healthcheck.conf │ └── version.sh ├── script │ ├── cibuild │ └── test └── test │ ├── lib.sh │ └── test-basic.sh ├── glb-redirect ├── Makefile ├── README.md ├── dkms.conf ├── install-ipt.sh ├── ipt_GLBREDIRECT.c ├── ipt_glbredirect.h ├── libxt_GLBREDIRECT.c ├── script │ └── test └── tests │ ├── glb_test_remote_snoop.py │ ├── glb_test_utils.py │ ├── test_glb_redirect_v4_on_v4.py │ └── test_glb_redirect_v6_on_v4.py ├── glb-wireshark-dissector ├── README.md └── init.lua └── scapy-glb-gue ├── README.md └── glb_scapy ├── __init__.py └── glb_gue_scapy.py /.github/codeql/codeql-config.yml: -------------------------------------------------------------------------------- 1 | paths-ignore: 2 | - test 3 | - vendor -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: github-actions 5 | directory: "/" 6 | schedule: 7 | interval: daily 8 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: [push] 4 | 5 | jobs: 6 | package-build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: Run package build focal 13 | run: script/cibuild-create-packages-focal 14 | - name: Tar files 15 | run: tar -cvf glb-director.tar $GITHUB_WORKSPACE/tmp/build 16 | - name: Upload Artifact 17 | uses: actions/upload-artifact@v4 18 | with: 19 | name: glb-director 20 | path: glb-director.tar -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | "on": 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [ master ] 9 | schedule: 10 | - cron: '29 15 * * 5' 11 | 12 | jobs: 13 | analyze_go_python: 14 | name: Analyze Go and Python 15 | runs-on: ubuntu-latest 16 | permissions: 17 | actions: read 18 | contents: read 19 | security-events: write 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | language: [ go, python ] 25 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 26 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 27 | 28 | steps: 29 | - name: Checkout repository 30 | uses: actions/checkout@v4 31 | 32 | # Initializes the CodeQL tools for scanning. 33 | - name: Initialize CodeQL 34 | uses: github/codeql-action/init@v3 35 | with: 36 | languages: ${{ matrix.language }} 37 | # If you wish to specify custom queries, you can do so here or in a config file. 38 | # By default, queries listed here will override any specified in a config file. 39 | # Prefix the list here with "+" to use these queries and those in the config file. 40 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 41 | queries: security-and-quality 42 | config-file: ./.github/codeql/codeql-config.yml 43 | 44 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 45 | # If this step fails, then you should remove it and run the build manually (see below) 46 | - name: Autobuild 47 | uses: github/codeql-action/autobuild@v3 48 | 49 | - name: Perform CodeQL Analysis 50 | uses: github/codeql-action/analyze@v3 51 | 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | tmp 3 | src/glb-redirect/glb-redirect-iptables-dkms-mkdeb 4 | *.so 5 | *.o 6 | build 7 | .DS_Store 8 | *.pyc 9 | *.mk 10 | *.cmd 11 | src/glb-redirect/*/*.mod 12 | *.ko 13 | *.mod.c 14 | *.symvers 15 | *.order 16 | *.deb 17 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at opensource@github.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | [fork]: https://github.com/github/glb-director/fork 4 | [pr]: https://github.com/github/glb-director/compare 5 | [code-of-conduct]: CODE_OF_CONDUCT.md 6 | 7 | Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. 8 | 9 | Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [project's open source license](LICENSE.md). 10 | 11 | Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. 12 | 13 | ## Submitting a pull request 14 | 15 | 0. [Fork][fork] and clone the repository 16 | 0. Make sure the tests pass on your machine: `script/cibuild` 17 | 0. Create a new branch: `git checkout -b my-branch-name` 18 | 0. Make your change, add tests, and make sure the tests still pass 19 | 0. Push to your fork and [submit a pull request][pr] 20 | 0. Pat your self on the back and wait for your pull request to be reviewed and merged. 21 | 22 | Here are a few things you can do that will increase the likelihood of your pull request being accepted: 23 | 24 | - Write tests. 25 | - Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests. 26 | - Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). 27 | 28 | ## Resources 29 | 30 | - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) 31 | - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) 32 | - [GitHub Help](https://help.github.com) 33 | 34 | ## Releasing 35 | 36 | Currently each component in this repo is versioned and released separately as needed. The build and test process is automated requiring Docker (for building) and Vagrant (for multi-machine testing): 37 | ``` 38 | script/cibuild 39 | ``` 40 | 41 | Once this completes successfully, the `tmp/build` directory will contain a `.deb` file for each component and they can be released to the apt source by an authorised maintainer: 42 | ``` 43 | package_cloud push github/glb-director/debian/jessie glb-_.deb 44 | package_cloud push github/glb-director/debian/stretch glb-_.deb 45 | ``` 46 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | mkdeb: 2 | make -C src/glb-redirect mkdeb 3 | make -C src/glb-healthcheck mkdeb 4 | cd src/glb-director-xdp && script/create-packages 5 | cd src/glb-director && script/create-packages 6 | 7 | clean: 8 | make -C src/glb-redirect clean 9 | make -C src/glb-healthcheck clean 10 | make -C src/glb-director clean 11 | make -C src/glb-director/cli clean 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitHub Load Balancer Director 2 | 3 | The GitHub Load Balancer (GLB) Director is a set of components that provide a scalable set of stateless [Layer 4](https://en.wikipedia.org/wiki/Transport_layer) load balancer servers capable of line rate packet processing in bare metal datacenter environments, and is used in production to serve all traffic from GitHub's datacenters. 4 | 5 | ![GLB Logo](./docs/images/glb-logo-dark.png) 6 | 7 | ## Design 8 | 9 | GLB Director is designed to be used in datacenter environments where multiple servers can announce the same IP address via BGP and have network routers shard traffic amongst those servers using [ECMP routing](https://en.wikipedia.org/wiki/Equal-cost_multi-path_routing). While ECMP shards connections per-flow using consistent hashing, addition or removal of nodes will generally cause some disruption to traffic as state isn't stored for each flow. A split L4/L7 design is typically used to allow the L4 servers to redistribute these flows back to a consistent server in a flow-aware manner. GLB Director implements the L4 (director) tier of a split L4/L7 load balancer design. 10 | 11 | ![L4/L7 load balancer design](./docs/images/glb-component-overview.png) 12 | 13 | Traditional solutions such as [LVS](https://en.wikipedia.org/wiki/Linux_Virtual_Server) have stored flow state on each director node and then shared flow state between nodes. GLB Director instead receives these flows and uses a [derivative of rendezvous hashing](./docs/development/glb-hashing.md) to hash flows to a pair of servers with a pre-determined order, and [leverages the state already stored](./docs/development/second-chance-design.md) on those servers to allow flows to complete after a server begins draining. 14 | 15 | ![GLB "second chance" packet flow](./docs/images/second-chance-nolegend.png) 16 | 17 | GLB Director only processes packets on ingress, and encapsulates them inside an [extended Generic UDP Encapsulation](./docs/development/gue-header.md) packet. Egress packets from proxy layer servers are sent directly to clients using Direct Server Return. 18 | 19 | ## Getting started 20 | 21 | GLB Director has a number of components that work together with other infrastructure components to create a complete load balancer. We've created an [example Vagrant setup/guide](./docs/setup/example-setup-vagrant.md) which will create a local instance of GLB with all required components. The [docs](./docs/) directory also contains additional documentation on the design and constraints. For details about the packages provided and how to install them, see the [packages and quick start guide](./docs/setup/packages-quick-start.md). 22 | 23 | ## Contributing 24 | 25 | Please check out our [contributing guidelines](CONTRIBUTING.md). 26 | 27 | ## License 28 | 29 | Components in this repository are licensed under BSD 3-Clause except where required to be GPL v2 depending on their dependencies and usage, see the [license documentation](./LICENSE.md) for detailed information. 30 | 31 | ## Authors 32 | 33 | GLB Director has been an ongoing project designed, authored, reviewed and supported by various members of GitHub's Production Engineering organisation, including: 34 | 35 | - [@joewilliams](https://github.com/joewilliams) 36 | - [@nautalice](https://github.com/nautalice) 37 | - [@ross](https://github.com/ross) 38 | - [@theojulienne](https://github.com/theojulienne) 39 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | ## Setup 4 | 5 | * [Example Vagrant Setup](./setup/example-setup-vagrant.md) - if you want to get all components up and running in a test environment and look around at how different GLB components work together. 6 | * [Known Compatible DPDK configurations](./setup/known-compatible-dpdk.md) - if you want to see examples of how GitHub configures DPDK in its datacenters, or how to use it on a public cloud provider that supports DPDK and BGP. 7 | * [Packages and quick start guide](./setup/packages-quick-start.md) - included packages and quick-start instructions for relevant files needed to configure them. 8 | * [glb-director component configuration options](./setup/glb-director-configuration.md) - configuration options for the GLB Director and discussion of NIC/Port and CPU Core configuration. 9 | * [Forwarding table configuration & healthchecks](./setup/forwarding-table-config.md) - Configuring the GLB forwarding table, and the director->proxy healthcheck process. 10 | * [Backend proxy server setup](./setup/backend-proxy-setup.md) - Configuring the backend TCP/proxy tier servers. 11 | 12 | Some notable known limitations / design decisions of the current implementation: 13 | * The datacenter internal MTU is expected to be large enough to encapsulate any user packet inside a GUE header. We use jumbo frames (9000+ MTU) within the datacenter with a transit/internet MTU of 1500. GLB Director will not fragment packets if they are too large. 14 | * If GLB is used within a datacenter, proxy servers should know the correct maximum MSS they can use. We tell `haproxy` to clamp MSS to a small enough value that it can always be encapsulated. 15 | * Because of the above 2 points, GLB Director doesn't send ICMP fragmentation required messages when it cannot forward packets. 16 | * GLB Director will, however, forward ICMP fragmentation required packets from outside to the correct proxy server. 17 | 18 | ## GLB Architecture 19 | 20 | * [GLB Hashing](./development/glb-hashing.md) - explains how the GLB forwarding table is generated and the way rendezvous hashing is used to maintain consistent server mapping for client IPs. 21 | * [Second Chance Design](./development/second-chance-design.md) - explains how GLB avoids storing or sharing connection state on the director tier, and compares to some other similar technologies. 22 | * [GUE Header](./development/gue-header.md) - lays out the fields of the GLB private data of the GUE (Generic UDP Encapsulation) header that GLB uses to encapsulate and tunnel packets. 23 | -------------------------------------------------------------------------------- /docs/images/ecmp-redist-break.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/ecmp-redist-break.png -------------------------------------------------------------------------------- /docs/images/ecmp-redist-glb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/ecmp-redist-glb.png -------------------------------------------------------------------------------- /docs/images/ecmp-redist-lvs-no-state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/ecmp-redist-lvs-no-state.png -------------------------------------------------------------------------------- /docs/images/forwarding-table-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/forwarding-table-active.png -------------------------------------------------------------------------------- /docs/images/forwarding-table-draining.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/forwarding-table-draining.png -------------------------------------------------------------------------------- /docs/images/forwarding-table-filling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/forwarding-table-filling.png -------------------------------------------------------------------------------- /docs/images/forwarding-table-removed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/forwarding-table-removed.png -------------------------------------------------------------------------------- /docs/images/glb-component-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/glb-component-overview.png -------------------------------------------------------------------------------- /docs/images/glb-logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/glb-logo-dark.png -------------------------------------------------------------------------------- /docs/images/glb-proxy-state-machine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/glb-proxy-state-machine.png -------------------------------------------------------------------------------- /docs/images/second-chance-nolegend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/second-chance-nolegend.png -------------------------------------------------------------------------------- /docs/images/second-chance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/images/second-chance.png -------------------------------------------------------------------------------- /docs/setup/backend-proxy-setup.md: -------------------------------------------------------------------------------- 1 | # Backend Proxy Tier Setup 2 | 3 | GLB Director operates on a 2-tier L4+L7 setup. Most of the work is done on the "director" tier, however the "proxy" tier that terminates TCP connections must also run the `glb-redirect` iptables module to allow [second chance flow](../development/second-chance-design.md) to function. 4 | 5 | ![L4/L7 load balancer design](../images/glb-component-overview.png) 6 | 7 | ## Configuring GUE 8 | 9 | GLB Director forwards packets using [GUE](../development/gue-header.md). Linux kernel 4.x supports this out of the box, and we've tested it with the Debian Stretch 4.9 series kernel. The proxy server must be configured to receive these GUE packets and decapsulate them. The following will configure them to do so, and can typically be enabled by configuration management: 10 | ``` 11 | # `fou` includes support for GUE as well as the basic FOU it's based on 12 | modprobe fou 13 | # designate port 19523 as having GUE-encoded data. 14 | ip fou add port 19523 gue 15 | ``` 16 | 17 | For load balancer IPs that use IPv4, ensure that `tunl0` is up and contains those IPs (GUE packets with IPv4 will be decapsulated here automatically): 18 | ``` 19 | ip link set up dev tunl0 20 | ip addr add /32 dev tunl0 21 | ``` 22 | 23 | For load balancer IPs that use IPv6, ensure that `sit0` is up and contains those IPs (GUE packets with IPv6 will be decapsulated here automatically): 24 | ``` 25 | modprobe sit 26 | ip link set up dev sit0 27 | ip addr add /128 dev sit0 28 | ``` 29 | 30 | ## Installing and configuring the iptables module 31 | 32 | To install the `glb-redirect` iptables module, the `glb-redirect-iptables-dkms` package will compile the module for the running kernel (and any new kernels installed). This will provide a new iptables target called `GLBREDIRECT` which implements the GLB [second chance flow](../development/second-chance-design.md). 33 | 34 | ``` 35 | # ensure we don't track these with conntrack (if in use), since they are not stateful 36 | sudo iptables -t raw -A INPUT -p udp -m udp --dport 19523 -j CT --notrack 37 | # process all packets through GLBREDIRECT to support second chance 38 | sudo iptables -A INPUT -p udp -m udp --dport 19523 -j GLBREDIRECT 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/setup/images/flow-paths.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/setup/images/flow-paths.png -------------------------------------------------------------------------------- /docs/setup/images/vagrant-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/docs/setup/images/vagrant-setup.png -------------------------------------------------------------------------------- /docs/setup/packages-quick-start.md: -------------------------------------------------------------------------------- 1 | # Packages and quick start guide 2 | 3 | GLB Director's components are packaged and ready to use along with a compatible DPDK version for Debian Jessie and Debian Stretch. 4 | 5 | ![L4/L7 load balancer design](../images/glb-component-overview.png) 6 | 7 | ## Installing the apt sources 8 | 9 | An unofficial DPDK release apt source is provided which provides a compatible DPDK version to use with GLB director - currently DPDK `17.11.1-6`: 10 | ``` 11 | curl -s https://packagecloud.io/install/repositories/github/unofficial-dpdk-stable/script.deb.sh | sudo bash 12 | ``` 13 | 14 | The GLB packages themselves are also available as an apt source: 15 | ``` 16 | curl -s https://packagecloud.io/install/repositories/github/glb-director/script.deb.sh | sudo bash 17 | ``` 18 | 19 | ## Director tier: `glb-director` 20 | 21 | The main `glb-director` DPDK application takes packets destined to a GLB IP and encapsulates them over a tunnel to one of the configured backend proxy servers. 22 | 23 | Installation on Debian: 24 | ``` 25 | sudo apt install glb-director 26 | ``` 27 | 28 | The following configuration files need to be adjusted, see [glb-director configuration](./glb-director-configuration.md) and [GLB forwarding table configuration](./forwarding-table-config.md) for more information: 29 | * `/etc/default/glb-director` - Configuration around the DPDK EAL runtime and other similar configuration options, used by systemd. 30 | * `/etc/glb/director.conf` - The default location for the configuration of how the director processes packets on CPU cores and on ports/NICs. 31 | * `/etc/glb/forwarding_table.json` - The default location for the forwarding table when healthchecking is not used. 32 | 33 | The glb-director runs with systemd under the `glb-director.service` unit. 34 | 35 | ## Director tier: `glb-healthcheck` 36 | 37 | The `glb-healthcheck` application runs tunnel and HTTP healthchecks on a source [GLB forwarding table](./forwarding-table-config.md), writing out a new table that `glb-director` can consume that takes into account health state of backend proxy servers. 38 | 39 | Installation on Debian: 40 | ``` 41 | sudo apt install glb-healthcheck 42 | ``` 43 | 44 | To configure the healthchecker to work with `glb-director`, the `/etc/default/glb-director` will need to be updated to reflect the `/etc/glb/forwarding_table.checked.bin` version. 45 | 46 | The following files are relevant to configuring the healthchecker itself, see [GLB forwarding table configuration](./forwarding-table-config.md) for more information: 47 | * `/etc/glb/healthcheck.conf` - The default location for the configuration of how the healthchecker performs its functions. 48 | * `/etc/glb/forwarding_table.src.json` - The default location for the forwarding table when healthchecking is used. 49 | * `/etc/glb/forwarding_table.checked.json` - Auto-generated by `glb-healthcheck`. 50 | 51 | The glb-healthcheck runs with systemd under the `glb-healthcheck.service` unit. 52 | 53 | ## Proxy tier: `glb-redirect-iptables-dkms` 54 | 55 | The `glb-redirect-iptables-dkms` package uses [DKMS](https://en.wikipedia.org/wiki/Dynamic_Kernel_Module_Support) to create and maintain an iptables module for GLB purposes that works on the currently running kernel. 56 | 57 | Installation on Debian: 58 | ``` 59 | sudo apt install glb-redirect-iptables-dkms 60 | ``` 61 | 62 | This package provides the `GLB-REDIRECT` iptables target, see [Backend Proxy Setup](./backend-proxy-setup.md) for more information on configuring proxy tier servers including usage of this iptables module. 63 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | nose==1.3.7 2 | pyroute2==0.5.19 3 | scapy==2.4.5 4 | siphash==0.0.1 5 | netaddr=0.8.0 6 | -------------------------------------------------------------------------------- /script/Dockerfile.focal: -------------------------------------------------------------------------------- 1 | FROM ubuntu:focal 2 | 3 | RUN apt-get update && apt-get -y install curl git 4 | 5 | # DPDK 6 | RUN echo "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main universe" >> /etc/apt/sources.list 7 | ARG DEBIAN_FRONTEND=noninteractive 8 | RUN apt-get update && apt-get install -y build-essential dpdk=17.11.1-6 dpdk-dev=17.11.1-6 libdpdk-dev=17.11.1-6 wget pkg-config libjansson-dev libsystemd-dev 9 | 10 | # iptables / DKMS 11 | ARG DEBIAN_FRONTEND=noninteractive 12 | RUN apt-get update && apt-get install -y -f wget pkg-config libsystemd-dev dkms debhelper libxtables-dev 13 | 14 | # golang 15 | RUN wget --quiet https://golang.org/dl/go1.20.5.linux-amd64.tar.gz -O- | tar -C /usr/local -zxvf - 16 | ENV GOROOT /usr/local/go 17 | ENV GOPATH /go 18 | ENV PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}" 19 | 20 | # fpm for packaging 21 | RUN apt-get update && apt-get install -y ruby ruby-dev rubygems build-essential 22 | 23 | # See fpm dependency breakage issue: https://github.com/jordansissel/fpm/issues/1918 24 | RUN gem install --version 2.7.6 dotenv 25 | RUN gem install ffi -f 26 | RUN gem install rake fpm 27 | 28 | # XDP 29 | # linux-libc-dev must be upgraded to get a bpf.h that matches what we use. the rest match what we do in Vagrant for testing. 30 | RUN apt-get update && apt install -y apt-transport-https curl software-properties-common 31 | RUN apt-get update && apt install -y iproute2 libbpf-dev linux-libc-dev clang-10 32 | 33 | # Hack because the kernel headers are not installed in the right place (linuxkit vs generic) 34 | RUN ln -s /usr/src/$(ls /usr/src/ | grep generic) /usr/src/linux-headers-$(uname -r) 35 | 36 | # Hack for C99 math 37 | RUN sed -i '1s/^/#define __USE_C99_MATH\n/' /usr/src/$(ls /usr/src/ | grep generic)/include/linux/kasan-checks.h 38 | RUN sed -i '2s/^/#include \n/' /usr/src/$(ls /usr/src/ | grep generic)/include/linux/kasan-checks.h 39 | -------------------------------------------------------------------------------- /script/Dockerfile.stretch: -------------------------------------------------------------------------------- 1 | FROM debian:stretch 2 | 3 | RUN echo 'deb http://ftp.debian.org/debian stretch-backports main' >>/etc/apt/sources.list 4 | RUN apt-get update && apt-get -y install curl git 5 | 6 | # DPDK 7 | RUN curl -s https://packagecloud.io/install/repositories/github/unofficial-dpdk-stable/script.deb.sh | bash 8 | RUN apt-get update && apt-get install -y build-essential dpdk dpdk-dev wget pkg-config libjansson-dev libsystemd-dev 9 | 10 | # iptables / DKMS 11 | RUN apt-get update && apt-get install -y iptables-dev dkms debhelper libxtables-dev 12 | 13 | # golang 14 | RUN wget --quiet https://golang.org/dl/go1.14.8.linux-amd64.tar.gz -O- | tar -C /usr/local -zxvf - 15 | ENV GOROOT /usr/local/go 16 | ENV GOPATH /go 17 | ENV PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}" 18 | 19 | # fpm for packaging 20 | RUN apt-get update && apt-get install -y ruby ruby-dev rubygems build-essential 21 | # pin fpm 1.11.0 until https://github.com/jordansissel/fpm/pull/1752 is fixed 22 | RUN gem install --no-ri --no-rdoc rake fpm:1.11.0 23 | 24 | # patch DKMS for source package generation https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=832558 25 | ADD helpers/dkms.diff /root/dkms.diff 26 | RUN patch -d /usr/sbin /etc/bird/bird.conf </etc/glb/forwarding_table.src.json </etc/default/glb-director </etc/glb/director.conf </dev/null; do 117 | sleep 1 118 | echo 'Waiting for vglb_kni0 to come up...' 119 | done 120 | 121 | /sbin/ifconfig vglb_kni0 up "$local_ipv4_ip" 122 | fi 123 | 124 | if [[ "$tech_type" == "xdp" ]]; then 125 | cat >/etc/default/glb-director-xdp </etc/glb/director.conf </etc/systemd/system/glb-director-xdp.service.d/depend_on_shim.conf </etc/bird/bird.conf </etc/bird/bird.conf </dev/null 2>&1 38 | @@ -3112,6 +3095,7 @@ 39 | pushd "$temp_dir_debian" > /dev/null 2>&1 40 | case "$create_type" in 41 | dsc) 42 | + invoke_command "cp -Lpr '$dkms_tree/$module/$module_version/source' '$temp_dir_debian/$module-$module_version'" "Copying source tree" 43 | invoke_command "dpkg-buildpackage -S -us -uc 1>/dev/null" "Building source package" || \ 44 | die 7 $"There was a problem creating your ${create_type}." 45 | echo $"" 46 | @@ -3119,13 +3103,24 @@ 47 | invoke_command "mv '$temp_dir/${debian_package}-dkms_${module_version}_source.changes' '$temp_dir/${debian_package}-dkms_${module_version}.dsc' '$temp_dir/${debian_package}-dkms_${module_version}.tar.gz' '$deb_basedir'" "Moving built files to $deb_basedir" 48 | ;; 49 | deb) 50 | + invoke_command "cp -Lpr '$dkms_tree/$module/$module_version/source' '$temp_dir_debian/$module-$module_version'" "Copying source tree" 51 | invoke_command "dpkg-buildpackage -rfakeroot -d -b -us -uc 1>/dev/null" "Building binary package" || \ 52 | die 7 $"There was a problem creating your ${create_type}." 53 | echo $"" 54 | echo $"DKMS: mk${create_type} completed." 55 | - invoke_command "mv '$temp_dir/${debian_package}-dkms_${module_version}_${debian_build_arch}.deb' '$deb_basedir'" "Moving built files to $deb_basedir" 56 | + invoke_command "mv '$temp_dir/${debian_package}-dkms_${module_version}_all.deb' '$deb_basedir'" "Moving built files to $deb_basedir" 57 | ;; 58 | bmdeb) 59 | + # Only if we are shipping binary modules, make a .tgz for the deb 60 | + local archive_location="$dkms_tree/$module/$module_version/tarball/$module-$module_version.dkms.tar.gz" 61 | + binaries_only="binaries-only" 62 | + invoke_command "make_tarball" "Gathering binaries" 63 | + if [[ -f $archive_location ]]; then 64 | + invoke_command "cp '$archive_location' '$temp_dir_debian'" "Copying DKMS tarball into DKMS tree" 65 | + else 66 | + die 12 $"Unable to find created tarball." 67 | + fi 68 | + 69 | export KVER="$kernelver" 70 | export KARCH="$arch" 71 | invoke_command "dpkg-buildpackage -rfakeroot -d -b -us -uc 1>/dev/null" "Building binary package" || \ 72 | -------------------------------------------------------------------------------- /script/helpers/folding.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | begin_fold() { 4 | echo "%%%FOLD {$*}%%%" 5 | } 6 | 7 | end_fold() { 8 | echo "%%%END FOLD%%%" 9 | } 10 | -------------------------------------------------------------------------------- /script/helpers/prepare-vagrant: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | vagrant rsync "$*" 6 | -------------------------------------------------------------------------------- /script/helpers/test-snoop.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import SocketServer 4 | from scapy.all import * 5 | import struct, sys 6 | from scapy.all import L3RawSocket 7 | 8 | PORT = 9999 9 | 10 | class SnoopHandler(SocketServer.BaseRequestHandler): 11 | def forward_packet(self, packet): 12 | print('Forwarding packet: {}'.format(repr(packet))) 13 | sys.stdout.flush() 14 | # encapsulate the packet in an empty ethernet frame so the other side can decode more easily 15 | encap_packet = Ether(src='00:11:22:33:44:55', dst='00:11:22:33:44:55')/packet 16 | raw_data = str(encap_packet) 17 | try: 18 | self.request.sendall(struct.pack('!I', len(raw_data))) 19 | self.request.sendall(raw_data) 20 | except IOError: 21 | print('IOError, continuing') 22 | sys.stdout.flush() 23 | return False # probably broken pipe 24 | return True 25 | 26 | def handle(self): 27 | print('handling new client') 28 | sys.stdout.flush() 29 | 30 | # read the interface name from the remote side (prefixed by size) 31 | iface_len_raw = self.request.recv(6) 32 | ethertype, iface_len, = struct.unpack('!HI', iface_len_raw) 33 | iface = self.request.recv(iface_len).decode('ascii') 34 | print('listening on interface {} with ethertype 0x{:x}'.format(iface, ethertype)) 35 | sys.stdout.flush() 36 | 37 | s = L3RawSocket(iface=iface, type=ethertype) 38 | self.request.sendall('SYNC') # let the other side know we're ready (listening) 39 | while True: 40 | pkt = s.recv() 41 | if isinstance(pkt, IP) and isinstance(pkt.payload, TCP): 42 | if pkt.dport == PORT or pkt.sport == PORT: continue # don't talk about ourselves 43 | if not self.forward_packet(pkt): 44 | break 45 | 46 | class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 47 | pass 48 | 49 | if __name__ == "__main__": 50 | HOST, PORT = "0.0.0.0", PORT 51 | server = ThreadedTCPServer((HOST, PORT), SnoopHandler) 52 | server.serve_forever() 53 | -------------------------------------------------------------------------------- /script/helpers/test-snoop.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Test Snoop Service 3 | After=network.target 4 | 5 | [Service] 6 | Type=simple 7 | ExecStart=/vagrant/script/helpers/test-snoop.py 8 | Restart=on-failure 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /script/test-glb-director: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | HOSTPATH=$(cd $(dirname "$0") && cd .. && pwd) 6 | cd "$(dirname "$0")/.." 7 | 8 | . script/helpers/folding.sh 9 | 10 | vagrant ssh director-test -- bash /dev/stdin <<'EOF' 11 | cd /vagrant/src/glb-director 12 | sudo script/test 13 | EOF 14 | -------------------------------------------------------------------------------- /script/test-glb-director-xdp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | HOSTPATH=$(cd $(dirname "$0") && cd .. && pwd) 6 | cd "$(dirname "$0")/.." 7 | 8 | . script/helpers/folding.sh 9 | 10 | vagrant ssh director-test -- bash /dev/stdin <<'EOF' 11 | cd /vagrant/src/glb-director-xdp 12 | sudo script/test 13 | EOF 14 | -------------------------------------------------------------------------------- /script/test-glb-healthcheck: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | HOSTPATH=$(cd $(dirname "$0") && cd .. && pwd) 6 | cd "$(dirname "$0")/.." 7 | 8 | . script/helpers/folding.sh 9 | 10 | begin_fold "Testing glb-healthcheck daemon" 11 | ( 12 | vagrant ssh director-test -- sudo bash /dev/stdin <<'EOF' 13 | . /etc/profile.d/gopath.sh 14 | cd /vagrant/src/glb-healthcheck 15 | script/test 16 | EOF 17 | ) 18 | end_fold 19 | -------------------------------------------------------------------------------- /script/test-glb-redirect: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | HOSTPATH=$(cd $(dirname "$0") && cd .. && pwd) 6 | cd "$(dirname "$0")/.." 7 | 8 | . script/helpers/folding.sh 9 | 10 | begin_fold "Testing GLB-REDIRECT iptables module" 11 | ( 12 | vagrant ssh director-test -- bash /dev/stdin <<'EOF' 13 | cd /vagrant/src/glb-redirect 14 | sudo script/test 15 | EOF 16 | ) 17 | end_fold 18 | -------------------------------------------------------------------------------- /src/glb-director-xdp/.gitignore: -------------------------------------------------------------------------------- 1 | xdp-root-shim/xdp-root-shim -------------------------------------------------------------------------------- /src/glb-director-xdp/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | make -C xdp-root-shim/ 3 | make -C bpf/ 4 | go build -buildvcs=false -o glb-director-xdp main.go 5 | 6 | clean: 7 | make -C bpf/ clean 8 | rm -rf glb-director-xdp -------------------------------------------------------------------------------- /src/glb-director-xdp/bpf/Makefile: -------------------------------------------------------------------------------- 1 | all: glb_encap.o glb_encap_trace.o passer.o tailcall.o 2 | 3 | CLANG=clang-10 4 | LLC=llc-10 5 | 6 | ifeq ($(KVER),) 7 | KVER=$(shell uname -r) 8 | endif 9 | 10 | %.o: %.c 11 | $(CLANG) -c -O2 -emit-llvm -o - -D__KERNEL__ \ 12 | -Wall \ 13 | -Wno-gnu-variable-sized-type-not-at-end \ 14 | -Wno-address-of-packed-member \ 15 | -Wno-tautological-compare \ 16 | -Wno-unknown-warning-option \ 17 | -Wno-pointer-sign \ 18 | -Werror \ 19 | -include /usr/src/linux-headers-$(KVER:-amd64=-common)/include/linux/kconfig.h \ 20 | -I /usr/src/linux-headers-$(KVER:-amd64=-common)/arch/x86/include/uapi \ 21 | -I /usr/src/linux-headers-$(KVER:-amd64=-common)/arch/x86/include/uapi \ 22 | -I /usr/src/linux-headers-$(KVER:-amd64=-common)/include/uapi \ 23 | -I /usr/src/linux-headers-$(KVER:-amd64=-common)/include/uapi \ 24 | -I /usr/src/linux-headers-$(KVER:-amd64=-common)/include \ 25 | -I /usr/src/linux-headers-$(KVER)/include \ 26 | -I include/ \ 27 | -I ../.. \ 28 | $< > .tmp.ll 29 | $(LLC) -march=bpf -filetype=obj -o $@ .tmp.ll 30 | rm .tmp.ll 31 | 32 | clean: 33 | rm -rf *.o 34 | -------------------------------------------------------------------------------- /src/glb-director-xdp/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 | #include "bpf_helper_defs.h" 6 | 7 | #define __uint(name, val) int (*name)[val] 8 | #define __type(name, val) typeof(val) *name 9 | 10 | /* Helper macro to print out debug messages */ 11 | #define bpf_printk(fmt, ...) \ 12 | ({ \ 13 | char ____fmt[] = fmt; \ 14 | bpf_trace_printk(____fmt, sizeof(____fmt), \ 15 | ##__VA_ARGS__); \ 16 | }) 17 | 18 | /* 19 | * Helper macro to place programs, maps, license in 20 | * different sections in elf_bpf file. Section names 21 | * are interpreted by elf_bpf loader 22 | */ 23 | #define SEC(NAME) __attribute__((section(NAME), used)) 24 | 25 | #ifndef __always_inline 26 | #define __always_inline __attribute__((always_inline)) 27 | #endif 28 | #ifndef __weak 29 | #define __weak __attribute__((weak)) 30 | #endif 31 | 32 | /* 33 | * Helper structure used by eBPF C program 34 | * to describe BPF map attributes to libbpf loader 35 | */ 36 | #define BUF_SIZE_MAP_NS 256 37 | 38 | typedef struct bpf_map_def { 39 | unsigned int type; 40 | unsigned int key_size; 41 | unsigned int value_size; 42 | unsigned int max_entries; 43 | unsigned int map_flags; 44 | unsigned int pinning; 45 | char namespace[BUF_SIZE_MAP_NS]; 46 | } bpf_map_def; 47 | 48 | enum bpf_pin_type { 49 | PIN_NONE = 0, 50 | PIN_OBJECT_NS, 51 | PIN_GLOBAL_NS, 52 | PIN_CUSTOM_NS, 53 | }; 54 | 55 | enum libbpf_tristate { 56 | TRI_NO = 0, 57 | TRI_YES = 1, 58 | TRI_MODULE = 2, 59 | }; 60 | 61 | #define __kconfig __attribute__((section(".kconfig"))) 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/glb-director-xdp/bpf/glb_encap_limits.h: -------------------------------------------------------------------------------- 1 | #ifndef _GLB_ENCAP_LIMITS_H 2 | #define _GLB_ENCAP_LIMITS_H 3 | 4 | #include 5 | 6 | /* 7 | * The GLB forwarding table allows for bind ranges which has a port-range-start and port-range-end. 8 | * Since looping through those in XDP isn't possible (since looping structures aren't yet allowed in BPF), these ranges are expanded to individual port binds within the helper cgo. 9 | * The limit below defines the maximum supported number of binds in the map after the bind ranges have been expanded. 10 | */ 11 | #define BPF_MAX_BINDS 4096 12 | 13 | // Macro access function for cgo 14 | uint32_t bpf_max_binds() 15 | { 16 | return BPF_MAX_BINDS; 17 | } 18 | #endif 19 | -------------------------------------------------------------------------------- /src/glb-director-xdp/bpf/glb_encap_trace.c: -------------------------------------------------------------------------------- 1 | #define ENABLE_TRACE 1 2 | #include "glb_encap.c" -------------------------------------------------------------------------------- /src/glb-director-xdp/bpf/glb_stats.h: -------------------------------------------------------------------------------- 1 | #ifndef _GLB_STATS_H_ 2 | #define _GLB_STATS_H_ 3 | 4 | /* NOTE: these fields follow Go naming conventions, because they are an interface with 5 | * cgo which needs the fields to be capitalised to be exported and binary-unmarshal-able. 6 | */ 7 | 8 | typedef struct glb_global_stats { 9 | /* The number of packets entering the XDP pipeline */ 10 | uint64_t Processed; 11 | /* The number of packets that couldn't be parsed, meaning it wasn't the protocols we know how to parse. 12 | * This isn't always an error, since we listen for any packets on the host. 13 | */ 14 | uint64_t UnknownFormat; 15 | /* The number of packets that we could successfully parse, but then didn't match a bind. 16 | * This is also expected in production. 17 | */ 18 | uint64_t NoMatchingBind; 19 | /* The number of processed packets that matched a bind and should be included in the table stats */ 20 | uint64_t Matched; 21 | 22 | /* The number of packets that made it all the way through to encapsulation and transmit. */ 23 | uint64_t Encapsulated; 24 | 25 | /* The number of bytes that made it all the way through to encapsulation and transmit. 26 | * This includes the encapsulation overhead and ethernet frame header. 27 | */ 28 | uint64_t EncapsulatedBytes; 29 | 30 | /* The below errors are unexpected, and we generally expect none of them to occur. 31 | * They might be useful to debug why the system isn't behaving as expected 32 | */ 33 | 34 | /* Internal Error: Reference of a table that we then couldn't look up */ 35 | uint64_t ErrorTable; 36 | /* Internal Error: Reference of a table with no hashing secret */ 37 | uint64_t ErrorSecret; 38 | /* Internal Error: The hash field configuration couldn't be retrieved */ 39 | uint64_t ErrorHashConfig; 40 | /* Internal Error: We looked up a table, but the table didn't have a row where we expected */ 41 | uint64_t ErrorMissingRow; 42 | /* Internal Error: We tried to create space to encapsulate the packet (at the front), but this failed */ 43 | uint64_t ErrorCreatingSpace; 44 | /* Internal Error: The outbound gateway MAC address could not be read from configuration */ 45 | uint64_t ErrorMissingGatewayMAC; 46 | /* Internal Error: The local machine's source IP address could not be read from configuration */ 47 | uint64_t ErrorMissingSourceAddress; 48 | } glb_global_stats; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/glb-director-xdp/bpf/include/asm/barrier.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 | #ifndef __ASM_BARRIER_H 3 | #define __ASM_BARRIER_H 4 | 5 | #include 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /src/glb-director-xdp/bpf/passer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bpf_helpers.h" 3 | 4 | SEC("prog") 5 | int xdp_passer(struct xdp_md *ctx) { 6 | return XDP_PASS; 7 | } 8 | -------------------------------------------------------------------------------- /src/glb-director-xdp/bpf/tailcall.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018-present, Facebook, Inc. 2 | * 3 | * This program is free software; you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License as published by 5 | * the Free Software Foundation; version 2 of the License. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License along 13 | * with this program; if not, write to the Free Software Foundation, Inc., 14 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 15 | */ 16 | 17 | #include 18 | #include "bpf_helpers.h" 19 | 20 | #define ROOT_ARRAY_SIZE 3 21 | 22 | struct bpf_map_def SEC("maps") root_array = { 23 | .type = BPF_MAP_TYPE_PROG_ARRAY, 24 | .key_size = sizeof(__u32), 25 | .value_size = sizeof(__u32), 26 | .max_entries = ROOT_ARRAY_SIZE, 27 | }; 28 | 29 | SEC("xdp-root") 30 | int xdp_root(struct xdp_md *ctx) { 31 | #pragma clang loop unroll(full) 32 | for (__u32 i = 0; i < ROOT_ARRAY_SIZE; i++) { 33 | bpf_tail_call(ctx, &root_array, i); 34 | } 35 | return XDP_PASS; 36 | } 37 | 38 | char _license[] SEC("license") = "GPL"; 39 | -------------------------------------------------------------------------------- /src/glb-director-xdp/bpf/xdpcap_hook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2019, Cloudflare. 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 | * * Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * * 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 | * * 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 | */ 31 | 32 | #ifndef XDPCAP_HOOK_H 33 | #define XDPCAP_HOOK_H 34 | 35 | #include 36 | 37 | /** 38 | * Create a bpf map suitable for use as an xdpcap hook point. 39 | * 40 | * For example: 41 | * struct bpf_map_def xdpcap_hook = XDPCAP_HOOK(); 42 | */ 43 | #define XDPCAP_HOOK() { \ 44 | .type = BPF_MAP_TYPE_PROG_ARRAY, \ 45 | .key_size = sizeof(int), \ 46 | .value_size = sizeof(int), \ 47 | .max_entries = 5, \ 48 | } 49 | 50 | /** 51 | * Return action, exposing the action and input packet to xdpcap hook. 52 | * 53 | * return xdpcap_exit(ctx, &hook, XDP_PASS) 54 | * 55 | * is equivalent to: 56 | * 57 | * return XDP_PASS; 58 | */ 59 | __attribute__((__always_inline__)) 60 | static inline enum xdp_action xdpcap_exit(struct xdp_md *ctx, void *hook_map, enum xdp_action action) { 61 | // tail_call 62 | // Some headers define tail_call (Cilium), others bpf_tail_call (kernel self tests). Use the helper ID directly 63 | ((int (*)(struct xdp_md *, void *, int))12)(ctx, hook_map, action); 64 | return action; 65 | } 66 | 67 | #endif /* XDPCAP_HOOK_H */ 68 | -------------------------------------------------------------------------------- /src/glb-director-xdp/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/github/glb-director/src/glb-director-xdp 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/DataDog/datadog-go v4.0.0+incompatible 7 | github.com/cilium/ebpf v0.0.0-20200901135951-4048cd641690 8 | github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf 9 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 10 | github.com/stretchr/testify v1.8.4 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /src/glb-director-xdp/go.sum: -------------------------------------------------------------------------------- 1 | github.com/DataDog/datadog-go v4.0.0+incompatible h1:Dq8Dr+4sV1gBO1sHDWdW+4G+PdsA+YSJOK925MxrrCY= 2 | github.com/DataDog/datadog-go v4.0.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= 3 | github.com/cilium/ebpf v0.0.0-20200901135951-4048cd641690 h1:GpWvisoWNFzz/RB0fMgyYUcFmF4G5MlYD9uUHoofayo= 4 | github.com/cilium/ebpf v0.0.0-20200901135951-4048cd641690/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= 5 | github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= 6 | github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 7 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 8 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 9 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= 11 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= 12 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 13 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 14 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 15 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 16 | github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= 17 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 18 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 19 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 20 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 21 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 22 | golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= 23 | golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 24 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 25 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 26 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 27 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 28 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 29 | -------------------------------------------------------------------------------- /src/glb-director-xdp/packaging/after-upgrade-custom-systemd.sh: -------------------------------------------------------------------------------- 1 | # until https://github.com/jordansissel/fpm/pull/1498 lands in a gem release, 2 | # this postinstall/postupgrade script prevents anything other than a daemon-reload 3 | # from taking place (since we don't want enable or start because xdp-root-shim needs 4 | # manual configuration) 5 | 6 | systemctl --system daemon-reload >/dev/null || true 7 | 8 | # return to disable existing stuff, this is actually injected in the script 9 | # https://github.com/c-ameron/fpm/blob/71c46b95c53d534a048433d9e66f50af41c63676/templates/deb/postinst_upgrade.sh.erb#L7-L9 10 | return 0 11 | -------------------------------------------------------------------------------- /src/glb-director-xdp/packaging/glb-director-xdp: -------------------------------------------------------------------------------- 1 | GLB_DIRECTOR_XDP_ROOT_PATHS="--xdp-root-path=/sys/fs/bpf/xdp_root_array@eth0" 2 | GLB_DIRECTOR_XDP_CONFIG_FILE="/etc/glb/director.conf" 3 | GLB_DIRECTOR_XDP_FORWARDING_TABLE="/etc/glb/forwarding_table.bin" 4 | GLB_DIRECTOR_XDP_BPF_PROGRAM="/usr/share/glb-director-xdp/glb_encap.o" 5 | GLB_DIRECTOR_XDP_EXTRA_ARGS="" 6 | -------------------------------------------------------------------------------- /src/glb-director-xdp/packaging/glb-director-xdp.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=GLB Director XDP 3 | After=network.target network-online.target 4 | Wants=network-online.target 5 | 6 | [Service] 7 | # Allow the service to notify systemd when it has finished activating. 8 | Type=notify 9 | # NotifyAccess will allow the main pid to send the above ready message (which is also the default). 10 | NotifyAccess=main 11 | Restart=on-failure 12 | EnvironmentFile=/etc/default/glb-director-xdp 13 | ExecStart=/bin/sh -c "exec /usr/sbin/glb-director-xdp ${GLB_DIRECTOR_XDP_ROOT_PATHS} --pid-file=/run/glb-director-xdp.pid --config-file=${GLB_DIRECTOR_XDP_CONFIG_FILE} --forwarding-table=${GLB_DIRECTOR_XDP_FORWARDING_TABLE} --bpf-program=${GLB_DIRECTOR_XDP_BPF_PROGRAM} ${GLB_DIRECTOR_XDP_EXTRA_ARGS}" 14 | ExecReload=/bin/sh -c '/bin/kill -USR1 $(cat /run/glb-director-xdp.pid)' 15 | PIDFile=/run/glb-director-xdp.pid 16 | TimeoutStopSec=3 17 | 18 | [Install] 19 | WantedBy=multi-user.target 20 | -------------------------------------------------------------------------------- /src/glb-director-xdp/packaging/version.sh: -------------------------------------------------------------------------------- 1 | . ../glb-director/packaging/version.sh 2 | 3 | # keep these in lock step for now to make it easier to reason about 4 | GLB_DIRECTOR_XDP_VERSION="${GLB_DIRECTOR_VERSION}" 5 | 6 | XDP_ROOT_SHIM_VERSION="0.0.2" 7 | -------------------------------------------------------------------------------- /src/glb-director-xdp/packaging/xdp-root-shim: -------------------------------------------------------------------------------- 1 | BPFFS_INTERFACE_PREFIX='/sys/fs/bpf/xdp_root_array@' 2 | -------------------------------------------------------------------------------- /src/glb-director-xdp/packaging/xdp-root-shim@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=XDP Root Shim provides a root array to bind and replace XDP programs on a given interface 3 | After=network.target 4 | Before=network-online.target 5 | Wants=network.target 6 | 7 | [Service] 8 | # Allow the service to notify systemd when it has finished activating. 9 | Type=notify 10 | # NotifyAccess will allow the main pid to send the above ready message (which is also the default). 11 | NotifyAccess=main 12 | Restart=always 13 | EnvironmentFile=/etc/default/xdp-root-shim 14 | ExecStart=/usr/sbin/xdp-root-shim /usr/share/xdp-root-shim/tailcall.o ${BPFFS_INTERFACE_PREFIX}%i %i 15 | TimeoutStopSec=3 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /src/glb-director-xdp/script/create-packages: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # BSD 3-Clause License 4 | # 5 | # Copyright (c) 2020 GitHub. 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # * Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from 20 | # this software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | set -e 34 | ROOTDIR=$(dirname $0)/.. 35 | cd $ROOTDIR 36 | 37 | . packaging/version.sh 38 | 39 | make -C ../glb-director/cli 40 | make 41 | 42 | ../glb-director/cli/glb-director-cli build-config ../glb-director/packaging/forwarding_table.json ../glb-director/packaging/forwarding_table.bin 43 | 44 | fpm -f -s dir -t deb \ 45 | -n glb-director-xdp \ 46 | -v ${GLB_DIRECTOR_XDP_VERSION} \ 47 | -d "xdp-root-shim" \ 48 | -d "libbpf0" \ 49 | -d "glb-director-cli >= ${GLB_DIRECTOR_VERSION}" \ 50 | --conflicts 'glb-director' \ 51 | --license 'BSD 3-Clause' \ 52 | --maintainer 'GitHub ' \ 53 | --deb-systemd packaging/glb-director-xdp.service \ 54 | --after-upgrade packaging/after-upgrade-custom-systemd.sh \ 55 | --after-install packaging/after-upgrade-custom-systemd.sh \ 56 | --config-files /etc \ 57 | glb-director-xdp=/usr/sbin/ \ 58 | bpf/glb_encap.o=/usr/share/glb-director-xdp/ \ 59 | bpf/glb_encap_trace.o=/usr/share/glb-director-xdp/ \ 60 | ../glb-director/packaging/director.conf=/etc/glb/ \ 61 | ../glb-director/packaging/forwarding_table.bin=/etc/glb/ \ 62 | packaging/glb-director-xdp=/etc/default/ 63 | 64 | fpm -f -s dir -t deb \ 65 | -n xdp-root-shim \ 66 | -v ${XDP_ROOT_SHIM_VERSION} \ 67 | -d "libbpf0" \ 68 | --license 'BSD 3-Clause' \ 69 | --maintainer 'GitHub ' \ 70 | --deb-systemd packaging/xdp-root-shim\@.service \ 71 | --after-upgrade packaging/after-upgrade-custom-systemd.sh \ 72 | --after-install packaging/after-upgrade-custom-systemd.sh \ 73 | --config-files /etc \ 74 | xdp-root-shim/xdp-root-shim=/usr/sbin/ \ 75 | bpf/tailcall.o=/usr/share/xdp-root-shim/ \ 76 | packaging/xdp-root-shim=/etc/default/ 77 | 78 | if [ -d "$BUILDDIR" ]; then 79 | cp glb-director-xdp_${GLB_DIRECTOR_XDP_VERSION}_amd64.deb $BUILDDIR/ 80 | cp xdp-root-shim_${XDP_ROOT_SHIM_VERSION}_amd64.deb $BUILDDIR/ 81 | fi 82 | 83 | make clean 84 | -------------------------------------------------------------------------------- /src/glb-director-xdp/script/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # BSD 3-Clause License 4 | # 5 | # Copyright (c) 2018 GitHub. 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # * Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from 20 | # this software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | set -e 34 | 35 | export BASEDIR=$(cd $(dirname "$0") && cd .. && pwd) 36 | cd "$(dirname "$0")/.." 37 | 38 | export GOPATH=/go 39 | export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin 40 | 41 | . ../../script/helpers/folding.sh 42 | 43 | begin_fold "Building glb-director-xdp for testing" 44 | ( 45 | make -j4 -C ../glb-director/cli 46 | make # scan-build bricks go 47 | ) 48 | end_fold 49 | 50 | begin_fold "Running scapy packet tests against glb-director XDP" 51 | ( 52 | GLB_DIRECTOR_TYPE="xdp" PYTHONPATH=$(pwd)/../scapy-glb-gue/:$PYTHONPATH nosetests -v -w ../glb-director -a '!director_type' -a 'director_type=xdp' 53 | ) 54 | end_fold 55 | -------------------------------------------------------------------------------- /src/glb-director-xdp/xdp-root-shim/Makefile: -------------------------------------------------------------------------------- 1 | all: xdp-root-shim 2 | 3 | xdp-root-shim: 4 | cc xdp-root-shim.c -o xdp-root-shim -lbpf -lsystemd -------------------------------------------------------------------------------- /src/glb-director-xdp/xdp-root-shim/xdp-root-shim.c: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2020 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | int main(int argc, char **argv) { 42 | if (argc != 4) { 43 | fprintf(stderr, "Usage: %s \n", argv[0]); 44 | return 1; 45 | } 46 | 47 | const char *tailcall_elf_path = argv[1]; 48 | const char *bpffs_path = argv[2]; 49 | const char *iface_name = argv[3]; 50 | 51 | /* get more resources */ 52 | struct rlimit rl = {}; 53 | if (getrlimit(RLIMIT_MEMLOCK, &rl) != 0) { 54 | fprintf(stderr, "getrlimit RLIMIT_MEMLOCK failed\n"); 55 | return 1; 56 | } 57 | 58 | rl.rlim_max = RLIM_INFINITY; 59 | rl.rlim_cur = rl.rlim_max; 60 | 61 | if (setrlimit(RLIMIT_MEMLOCK, &rl) != 0) { 62 | fprintf(stderr, "setrlimit RLIMIT_MEMLOCK failed\n"); 63 | return 1; 64 | } 65 | 66 | /* make sure we have a valid interface */ 67 | int iface_index = if_nametoindex(iface_name); 68 | if (iface_index == 0) { 69 | fprintf(stderr, "Could not find interface '%s'\n", iface_name); 70 | return 1; 71 | } 72 | 73 | /* load the tailcall bpf */ 74 | struct bpf_prog_load_attr prog_load_attr = { 75 | .prog_type = BPF_PROG_TYPE_XDP, 76 | .file = tailcall_elf_path, 77 | }; 78 | struct bpf_object *shim_obj; 79 | int prog_fd; 80 | 81 | if (bpf_prog_load_xattr(&prog_load_attr, &shim_obj, &prog_fd)){ 82 | fprintf(stderr, "Could not load '%s'\n", prog_load_attr.file); 83 | return 1; 84 | } 85 | 86 | /* pin the map to the */ 87 | struct bpf_map *root_array = bpf_object__find_map_by_name(shim_obj, "root_array"); 88 | 89 | unlink(bpffs_path); 90 | if (bpf_map__pin(root_array, bpffs_path) != 0) { 91 | fprintf(stderr, "Could not pin root array map to '%s'\n", bpffs_path); 92 | return 1; 93 | } 94 | 95 | /* bind it to the interface with XDP */ 96 | if (bpf_set_link_xdp_fd(iface_index, prog_fd, 0) < 0) { 97 | fprintf(stderr, "Could not attach XDP program to interface '%s'\n", iface_name); 98 | return 1; 99 | } 100 | 101 | sd_notify(0, "READY=1"); 102 | 103 | while (1) sleep(1); 104 | } 105 | -------------------------------------------------------------------------------- /src/glb-director/.gitignore: -------------------------------------------------------------------------------- 1 | *.cmd 2 | *.o.d 3 | _* 4 | *.map 5 | /glb-director 6 | *.deb 7 | -------------------------------------------------------------------------------- /src/glb-director/Makefile: -------------------------------------------------------------------------------- 1 | # BSD LICENSE 2 | # 3 | # Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 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 8 | # are met: 9 | # 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above copyright 13 | # notice, this list of conditions and the following disclaimer in 14 | # the documentation and/or other materials provided with the 15 | # distribution. 16 | # * Neither the name of Intel Corporation nor the names of its 17 | # contributors may be used to endorse or promote products derived 18 | # from this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | # Default SDK and target, can be overriden by command line or environment 33 | RTE_SDK ?= /usr/share/dpdk 34 | RTE_TARGET ?= x86_64-default-linuxapp-gcc 35 | 36 | include $(RTE_SDK)/mk/rte.vars.mk 37 | 38 | # binary name 39 | APP = glb-director 40 | 41 | # all source are stored in SRCS-y 42 | SRCS-y := main.c bind_classifier.c glb_kni.c glb_fwd_config.c \ 43 | glb_encap.c glb_encap_dpdk.c glb_control_loop.c glb_processor_loop.c \ 44 | siphash24.c glb_director_config.c statsd-client.c shared_opt.c 45 | 46 | #WERROR_FLAGS += -Werror 47 | 48 | CFLAGS += -O3 -g 49 | CFLAGS += $(WERROR_FLAGS) 50 | CFLAGS += -pie -fPIE -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -fstack-protector-strong 51 | CFLAGS += -DSTATSD 52 | CFLAGS += -DSYSTEMD 53 | #CFLAGS += -DGLB_DUMP_FULL_PACKET 54 | CFLAGS += -I$(SRCDIR)/../ # for 55 | 56 | LDFLAGS += -z relro -z now 57 | LDFLAGS += -ljansson 58 | LDFLAGS += -lsystemd 59 | 60 | # disable since libxenstore.so isn't linked properly 61 | CONFIG_RTE_LIBRTE_PMD_XENVIRT = n 62 | 63 | include $(RTE_SDK)/mk/rte.extapp.mk 64 | -------------------------------------------------------------------------------- /src/glb-director/README.md: -------------------------------------------------------------------------------- 1 | # glb-director 2 | 3 | The `glb-director` is a DPDK application that performs packet encapsulation using the [GLB extension to GUE](../../docs/development/gue-header.md). 4 | 5 | ## License 6 | 7 | The `glb-director` component contained within this directory is [licensed](../../LICENSE.md) under the BSD 3-Clause License, with the exception of Python test files which are GPL v2 for compatibility with Scapy. 8 | -------------------------------------------------------------------------------- /src/glb-director/bind_classifier.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * Copyright (c) 2016 Intel Corporation. (original DPDK example code) 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * * Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | 37 | #define CLASSIFIED_BITMASK 0x100000 38 | #define CLASSIFIED(x) ((x)&CLASSIFIED_BITMASK) 39 | #define CLASSIFIED_TABLE(x) ((x)-CLASSIFIED_BITMASK) 40 | 41 | struct glb_fwd_config_content; 42 | 43 | int create_bind_classifier(struct glb_fwd_config_content *config, 44 | struct rte_acl_ctx **ipv4_ctx_ptr, 45 | struct rte_acl_ctx **ipv6_ctx_ptr); 46 | int classify_to_tables(struct rte_acl_ctx *classifier_v4, 47 | struct rte_acl_ctx *classifier_v6, 48 | struct rte_mbuf **pkts_burst, uint32_t *classifications, 49 | unsigned int num_packets); 50 | -------------------------------------------------------------------------------- /src/glb-director/cli/.gitignore: -------------------------------------------------------------------------------- 1 | glb-config-check 2 | glb-director-cli 3 | glb-director-pcap 4 | glb-director-stub-server -------------------------------------------------------------------------------- /src/glb-director/cli/Makefile: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License 2 | # 3 | # Copyright (c) 2018 GitHub. 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 | # * Redistributions of source code must retain the above copyright notice, this 10 | # list of conditions and the following disclaimer. 11 | # 12 | # * 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 | # * 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 | 31 | all: glb-director-cli glb-config-check glb-director-pcap glb-director-stub-server 32 | 33 | CHECK_SRCS = config_check.c \ 34 | ../glb_control_loop.c \ 35 | ../glb_fwd_config.c \ 36 | ../bind_classifier.c \ 37 | ../glb_director_config.c \ 38 | ../siphash24.c \ 39 | ../shared_opt.c 40 | 41 | PCAP_SRCS = pcap_mode.c \ 42 | ../glb_fwd_config.c \ 43 | ../glb_director_config.c \ 44 | ../glb_encap.c \ 45 | ../cmdline_parse.c \ 46 | ../cmdline_parse_etheraddr.c \ 47 | ../glb_encap_pcap.c \ 48 | ../siphash24.c \ 49 | ../shared_opt.c 50 | 51 | STUB_SRCS = stub_server.c \ 52 | ../glb_fwd_config.c \ 53 | ../glb_director_config.c \ 54 | ../glb_encap.c \ 55 | ../cmdline_parse.c \ 56 | ../cmdline_parse_etheraddr.c \ 57 | ../glb_encap_pcap.c \ 58 | ../siphash24.c \ 59 | ../shared_opt.c 60 | 61 | CFLAGS += -Wall 62 | 63 | #WERROR_FLAGS += -Werror 64 | 65 | CFLAGS += -O3 -g 66 | CFLAGS += $(WERROR_FLAGS) 67 | CFLAGS += -pie -fPIE -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 68 | CFLAGS += -fstack-protector-all 69 | CFLAGS += -DCLI_MODE 70 | 71 | LDFLAGS += -z relro -z now 72 | LDFLAGS += -ljansson 73 | 74 | glb-director-cli: main.c 75 | gcc \ 76 | $(CFLAGS) \ 77 | -I`pwd`/.. \ 78 | -I`pwd`/../.. \ 79 | main.c \ 80 | ../siphash24.c $(LDFLAGS)\ 81 | -o glb-director-cli 82 | 83 | glb-config-check: 84 | gcc \ 85 | $(CFLAGS) \ 86 | $(CHECK_SRCS) \ 87 | -o glb-config-check \ 88 | -I`pwd`/.. \ 89 | -I`pwd`/../.. \ 90 | -I/usr/include/dpdk \ 91 | -I/usr/include/x86_64-linux-gnu \ 92 | -ldpdk -lpcap $(LDFLAGS)\ 93 | -m64 -mssse3 94 | 95 | glb-director-pcap: 96 | gcc \ 97 | $(CFLAGS) \ 98 | $(PCAP_SRCS) \ 99 | -o glb-director-pcap \ 100 | -I`pwd`/.. \ 101 | -I`pwd`/../.. \ 102 | -I/usr/include/dpdk \ 103 | -I/usr/include/x86_64-linux-gnu \ 104 | -lpcap \ 105 | -DPCAP_MODE $(LDFLAGS)\ 106 | -m64 -mssse3 107 | 108 | glb-director-stub-server: 109 | gcc \ 110 | $(CFLAGS) \ 111 | $(STUB_SRCS) \ 112 | -o glb-director-stub-server \ 113 | -I`pwd`/.. \ 114 | -I`pwd`/../.. \ 115 | -I/usr/include/dpdk \ 116 | -I/usr/include/x86_64-linux-gnu \ 117 | -DPCAP_MODE $(LDFLAGS)\ 118 | -m64 -mssse3 119 | 120 | clean: 121 | rm -rf glb-director-cli glb-config-check glb-director-pcap glb-director-stub-server 122 | -------------------------------------------------------------------------------- /src/glb-director/cli/config_check.c: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "bind_classifier.h" 34 | #include "config.h" 35 | #include "glb_control_loop.h" 36 | #include "glb_director_config.h" 37 | #include "glb_encap.h" 38 | #include "glb_fwd_config.h" 39 | #include "glb_processor_loop.h" 40 | #include "shared_opt.h" 41 | 42 | #include 43 | 44 | char config_file[256]; 45 | char forwarding_table[256]; 46 | 47 | struct glb_processor_ctx *glb_lcore_contexts[RTE_MAX_LCORE] = {NULL}; 48 | struct rte_mempool *glb_processor_msg_pool = NULL; 49 | 50 | int main(int argc, char **argv) 51 | { 52 | int ret = 0; 53 | 54 | /* Initialise EAL*/ 55 | glb_log_info("Initialising EAL"); 56 | ret = rte_eal_init(argc, argv); 57 | if (ret < 0) { 58 | glb_log_error_and_exit("Could not initialise EAL (%d)", ret); 59 | } 60 | 61 | argc -= ret; 62 | argv += ret; 63 | 64 | /* Find any command line options */ 65 | get_options(config_file, forwarding_table, argc, argv); 66 | 67 | glb_log_info("Loading GLB configuration"); 68 | g_director_config = 69 | glb_director_config_load_file(config_file, forwarding_table); 70 | 71 | glb_log_info("Processing GLB config"); 72 | struct glb_fwd_config_ctx *config_ctx = load_glb_fwd_config(); 73 | 74 | if (config_ctx->bind_classifier_v4 == NULL && 75 | config_ctx->bind_classifier_v6 == NULL) { 76 | glb_log_error_and_exit("Expecting at least one initial bind " 77 | "classifier creation to succeed."); 78 | } 79 | 80 | glb_log_info("GLB config context: %p", config_ctx); 81 | 82 | glb_fwd_config_dump(config_ctx); 83 | 84 | glb_log_info("Config ok!"); 85 | exit(0); 86 | } 87 | -------------------------------------------------------------------------------- /src/glb-director/cmdline_parse_etheraddr.h: -------------------------------------------------------------------------------- 1 | /* used in pcap mode */ 2 | 3 | /*- 4 | * BSD LICENSE 5 | * 6 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * * Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * * Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in 17 | * the documentation and/or other materials provided with the 18 | * distribution. 19 | * * Neither the name of Intel Corporation nor the names of its 20 | * contributors may be used to endorse or promote products derived 21 | * from this software without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | 36 | /* 37 | * Copyright (c) 2009, Olivier MATZ 38 | * All rights reserved. 39 | * Redistribution and use in source and binary forms, with or without 40 | * modification, are permitted provided that the following conditions are met: 41 | * 42 | * * Redistributions of source code must retain the above copyright 43 | * notice, this list of conditions and the following disclaimer. 44 | * * Redistributions in binary form must reproduce the above copyright 45 | * notice, this list of conditions and the following disclaimer in the 46 | * documentation and/or other materials provided with the distribution. 47 | * * Neither the name of the University of California, Berkeley nor the 48 | * names of its contributors may be used to endorse or promote products 49 | * derived from this software without specific prior written permission. 50 | * 51 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY 52 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 53 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 54 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 55 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 56 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 58 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 60 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 | */ 62 | 63 | #ifndef _PARSE_ETHERADDR_H_ 64 | #define _PARSE_ETHERADDR_H_ 65 | 66 | #include 67 | 68 | #ifdef __cplusplus 69 | extern "C" { 70 | #endif 71 | 72 | struct cmdline_token_etheraddr { 73 | struct cmdline_token_hdr hdr; 74 | }; 75 | typedef struct cmdline_token_etheraddr cmdline_parse_token_etheraddr_t; 76 | 77 | extern struct cmdline_token_ops cmdline_token_etheraddr_ops; 78 | 79 | int cmdline_parse_etheraddr(cmdline_parse_token_hdr_t *tk, const char *srcbuf, 80 | void *res, unsigned ressize); 81 | int cmdline_get_help_etheraddr(cmdline_parse_token_hdr_t *tk, char *dstbuf, 82 | unsigned int size); 83 | 84 | #define TOKEN_ETHERADDR_INITIALIZER(structure, field) \ 85 | { \ 86 | /* hdr */ \ 87 | { \ 88 | &cmdline_token_etheraddr_ops, /* ops */ \ 89 | offsetof(structure, field), /* offset */ \ 90 | }, \ 91 | } 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | 97 | #endif /* _PARSE_ETHERADDR_H_ */ 98 | -------------------------------------------------------------------------------- /src/glb-director/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * Copyright (c) 2016 Intel Corporation. (original DPDK example code) 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * * Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /* Macros for printing using RTE_LOG */ 35 | #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 36 | 37 | /* Max size of a single packet */ 38 | #define MAX_PACKET_SZ 9220 39 | 40 | /* Size of the data buffer in each mbuf */ 41 | #define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) 42 | 43 | /* Number of mbufs in mempool that is created, from docs: 44 | * The optimum size (in terms of memory usage) for a mempool 45 | * is when n is a power of two minus one: n = (2^q - 1). 46 | */ 47 | #define NB_MBUF ((8192 * 8) - 1) 48 | 49 | /* How many packets to attempt to read from NIC in one go */ 50 | #define PKT_BURST_SZ 32 51 | 52 | /* How many objects (mbufs) to keep in per-lcore mempool cache */ 53 | #define MEMPOOL_CACHE_SZ PKT_BURST_SZ 54 | 55 | /* Number of RX ring descriptors */ 56 | #define NB_RXD 128 57 | 58 | /* Number of TX ring descriptors */ 59 | #define NB_TXD 512 60 | 61 | #define MAX_KNI_PORTS 4 62 | 63 | /* default ethernet dev, used for collecting nic info */ 64 | #define DEFAULT_ETH_DEV 0 65 | -------------------------------------------------------------------------------- /src/glb-director/glb_control_loop.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * Copyright (c) 2016 Intel Corporation. (original DPDK example code) 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * * Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | struct glb_fwd_config_ctx *load_glb_fwd_config(void); 35 | int main_loop_control(__rte_unused void *arg); 36 | 37 | extern struct glb_processor_ctx *glb_lcore_contexts[RTE_MAX_LCORE]; 38 | extern struct rte_mempool *glb_processor_msg_pool; 39 | 40 | void signal_handler(int signum); 41 | -------------------------------------------------------------------------------- /src/glb-director/glb_director_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef _GLB_DIRECTOR_CONFIG_H 34 | #define _GLB_DIRECTOR_CONFIG_H 35 | #include 36 | 37 | #define MAX_FLOW_PATHS 32 38 | #define PER_CORE_MAX_FLOW_PATHS MAX_FLOW_PATHS 39 | 40 | #define CORE_WORKLOAD_NONE 0 41 | #define CORE_WORKLOAD_RX (1 << 0) 42 | #define CORE_WORKLOAD_TX (1 << 1) 43 | #define CORE_WORKLOAD_DIST (1 << 2) 44 | #define CORE_WORKLOAD_WORK (1 << 3) 45 | #define CORE_WORKLOAD_KNI (1 << 4) 46 | 47 | #define STATSD_PORT_DEFAULT 28125 48 | #define STATSD_IP "127.0.0.1" 49 | #define STATSD_NS "glb_director_ng" 50 | 51 | typedef struct { 52 | int rx_port_id; 53 | int rx_queue_id; 54 | 55 | int tx_port_id; 56 | int tx_queue_id; 57 | } glb_director_flow_path; 58 | 59 | typedef struct { 60 | uint32_t workloads; 61 | 62 | // for rx/tx 63 | uint32_t num_flow_paths; 64 | glb_director_flow_path flow_paths[MAX_FLOW_PATHS]; 65 | 66 | // for distributors 67 | uint32_t num_dist_workers; 68 | 69 | // for workers 70 | uint32_t source_dist_core; 71 | } glb_director_lcore_config; 72 | 73 | typedef struct { 74 | int src_addr; 75 | int dst_addr; 76 | int src_port; 77 | int dst_port; 78 | } glb_director_hash_fields; 79 | 80 | typedef struct { 81 | struct ether_addr local_ether_addr; 82 | 83 | struct ether_addr gateway_ether_addr; 84 | uint32_t local_ip_addr; 85 | 86 | int kni_enabled; 87 | uint32_t kni_ip; 88 | 89 | uint8_t nb_queues; 90 | 91 | char forwarding_table_path[PATH_MAX]; 92 | 93 | uint32_t num_flow_paths; 94 | glb_director_flow_path flow_paths[MAX_FLOW_PATHS]; 95 | 96 | glb_director_lcore_config lcore_configs[RTE_MAX_LCORE]; 97 | 98 | int forward_icmp_ping_responses; 99 | 100 | int rx_drop_en; 101 | 102 | /* Specify the fields to use as part of the hash calculation, 103 | * and optionally another set of fields to use (to allow safely 104 | * changing hash fields). 105 | */ 106 | glb_director_hash_fields hash_fields; 107 | int use_alt_hash_fields; 108 | glb_director_hash_fields alt_hash_fields; 109 | uint16_t statsd_port; 110 | } glb_director_config; 111 | 112 | glb_director_config * 113 | glb_director_config_load_file(const char *config_file, 114 | const char *forwarding_table); 115 | 116 | extern glb_director_config *g_director_config; 117 | #endif 118 | -------------------------------------------------------------------------------- /src/glb-director/glb_encap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | 34 | /* configure packet parsing to use linearisation space and the encap_packet_data_read hook */ 35 | #define GLB_PACKET_PARSING_LINEARISER 36 | const void *encap_packet_data_read(void *packet_data, uint32_t off, uint32_t len, void *buf); 37 | 38 | static void glb_log_info(const char *format, ...); /* let glb-hashing know this is linked */ 39 | 40 | #include 41 | #include 42 | 43 | struct glb_fwd_config_ctx; 44 | struct glb_fwd_config_content_table; 45 | 46 | int glb_calculate_packet_route(struct glb_fwd_config_ctx *ctx, unsigned int table_id, 47 | void *packet_data, glb_route_context *route_context); 48 | 49 | int glb_encapsulate_packet(struct ether_hdr *eth_hdr, glb_route_context *route_context); 50 | -------------------------------------------------------------------------------- /src/glb-director/glb_encap_dpdk.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * Copyright (c) 2016 Intel Corporation. (original DPDK example code) 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * * Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | int glb_encapsulate_packet_dpdk(struct glb_fwd_config_ctx *ctx, 35 | struct rte_mbuf *pkt, unsigned int table_id); 36 | 37 | int glb_checksum_offloading(struct rte_mbuf *pkt, struct ether_hdr *eth_hdr); 38 | -------------------------------------------------------------------------------- /src/glb-director/glb_encap_pcap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include 34 | 35 | typedef struct { 36 | int table_id; 37 | struct glb_fwd_config_ctx *ctx; 38 | } configuration; 39 | 40 | typedef struct { 41 | u_char *data; 42 | size_t len; 43 | } pcap_packet; 44 | 45 | void glb_pcap_handler(configuration args[], const struct pcap_pkthdr *pkthdr, 46 | const u_char *pkt); 47 | 48 | int glb_encapsulate_packet_pcap(struct glb_fwd_config_ctx *ctx, pcap_packet *pkt, 49 | unsigned int table_id); 50 | -------------------------------------------------------------------------------- /src/glb-director/glb_fwd_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #define GLB_FMT_MAGIC_WORD 0x44424c47 // 'GLBD' 34 | #define GLB_FMT_VERSION 2 35 | #define GLB_FMT_TABLE_ENTRIES 0x10000 36 | #define GLB_FMT_TABLE_HASHMASK 0xffff 37 | #define GLB_FMT_MAX_NUM_BACKENDS 0x100 38 | #define GLB_FMT_MAX_NUM_BINDS 0x100 39 | 40 | #define GLB_FMT_SECURE_KEY_BYTES 16 41 | 42 | #define FAMILY_IPV4 1 43 | #define FAMILY_IPV6 2 44 | 45 | /* we only support icmp, tcp, udp */ 46 | #define SUPPORTED_PROTOS_ICMP 1 47 | #define SUPPORTED_PROTOS_TCP 6 48 | #define SUPPORTED_PROTOS_UDP 17 49 | 50 | typedef enum { 51 | GLB_BACKEND_STATE_FILLING = 0, 52 | GLB_BACKEND_STATE_ACTIVE = 1, 53 | GLB_BACKEND_STATE_DRAINING = 2, 54 | } glb_fwd_config_host_state; 55 | 56 | typedef enum { 57 | GLB_BACKEND_HEALTH_DOWN = 0, 58 | GLB_BACKEND_HEALTH_UP = 1, 59 | } glb_fwd_config_host_health; 60 | 61 | struct glb_fwd_config_content_table_backend { 62 | uint32_t family; 63 | union { 64 | uint32_t ipv4_addr; 65 | uint8_t ipv6_addr[16]; 66 | }; 67 | uint16_t state; 68 | uint16_t healthy; 69 | } __attribute__((__packed__)); 70 | 71 | struct glb_fwd_config_content_table_bind { 72 | uint32_t family; 73 | union { 74 | uint32_t ipv4_addr; 75 | uint8_t ipv6_addr[16]; 76 | }; 77 | uint16_t ip_bits; 78 | 79 | uint16_t port_start; 80 | uint16_t port_end; 81 | uint8_t proto; 82 | uint8_t reserved; 83 | } __attribute__((__packed__)); 84 | 85 | struct glb_fwd_config_content_table_entry { 86 | uint32_t primary; 87 | uint32_t secondary; 88 | } __attribute__((__packed__)); 89 | 90 | struct glb_fwd_config_content_table { 91 | uint32_t num_backends; 92 | struct glb_fwd_config_content_table_backend 93 | backends[GLB_FMT_MAX_NUM_BACKENDS]; 94 | 95 | uint32_t num_binds; 96 | struct glb_fwd_config_content_table_bind binds[GLB_FMT_MAX_NUM_BINDS]; 97 | 98 | uint8_t secure_key[GLB_FMT_SECURE_KEY_BYTES]; 99 | struct glb_fwd_config_content_table_entry 100 | entries[GLB_FMT_TABLE_ENTRIES]; 101 | } __attribute__((__packed__)); 102 | 103 | struct glb_fwd_config_content { 104 | uint32_t magic_word; 105 | uint32_t version; 106 | uint32_t num_tables; 107 | uint32_t table_entries; 108 | uint32_t max_num_backends; 109 | uint32_t max_num_binds; 110 | 111 | struct glb_fwd_config_content_table tables[]; 112 | } __attribute__((__packed__)); 113 | 114 | struct glb_fwd_config_ctx { 115 | struct glb_fwd_config_content *raw_config; 116 | uint64_t raw_config_size; 117 | 118 | #ifndef NO_DPDK 119 | struct rte_acl_ctx *bind_classifier_v4; 120 | struct rte_acl_ctx *bind_classifier_v6; 121 | 122 | rte_atomic32_t _ref_count; 123 | #else 124 | uint32_t _ref_count; 125 | #endif 126 | }; 127 | 128 | struct glb_fwd_config_ctx *create_glb_fwd_config(const char *config_file); 129 | struct glb_fwd_config_ctx * 130 | glb_fwd_config_ctx_incref(struct glb_fwd_config_ctx *ctx); 131 | void glb_fwd_config_ctx_decref(struct glb_fwd_config_ctx *ctx); 132 | void glb_fwd_config_dump(struct glb_fwd_config_ctx *ctx); 133 | int check_config(struct glb_fwd_config_ctx *ctx); 134 | int supported_proto(int proto_num); 135 | -------------------------------------------------------------------------------- /src/glb-director/glb_kni.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * Copyright (c) 2016 Intel Corporation. (original DPDK example code) 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * * Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef GLB_KNI_H 35 | #define GLB_KNI_H 36 | 37 | #include 38 | 39 | typedef struct glb_kni_ glb_kni; 40 | 41 | /* Creates a GLB context for a KNI interface mapping to the given physical port. 42 | * The specified lcore is the one core that will be allowed to burst packets 43 | * directly to the KNI interface, while all other lcores will sent via an 44 | * intermediary queue. 45 | */ 46 | glb_kni *glb_kni_new(uint8_t physical_port_id, uint16_t rx_tx_queue_id, 47 | unsigned owner_lcore_id, struct rte_mempool *pktmbuf_pool); 48 | 49 | /* Safely send a burst of packets to the KNI port. 50 | * If the currently lcore owns this KNI port, the packets are bursted directly. 51 | * Otherwise, the packets are queued up for that lcore to send on the next call 52 | * to "glb_kni_lcore_queue_flush". 53 | */ 54 | unsigned glb_kni_safe_tx_burst(glb_kni *gk, struct rte_mbuf **kni_tx_burst, 55 | unsigned tx_burst_size); 56 | 57 | /* When called on the owning lcore: 58 | * - causes any queued packets to be sent to the KNI port. 59 | * - causes packets received from KNI to be sent to the NIC. 60 | */ 61 | void glb_kni_lcore_flush(glb_kni *gk); 62 | 63 | /* Handle housekeeping for the KNI interface. 64 | */ 65 | void glb_kni_handle_request(glb_kni *gk); 66 | 67 | /* Clean up KNI and allocated data. 68 | */ 69 | void glb_kni_release(glb_kni *gk); 70 | 71 | #endif // GLB_KNI_H 72 | -------------------------------------------------------------------------------- /src/glb-director/glb_processor_loop.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * Copyright (c) 2016 Intel Corporation. (original DPDK example code) 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * * Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | 36 | #include "glb_kni.h" 37 | #include "glb_director_config.h" 38 | 39 | typedef enum { 40 | GLB_CONTROL_MSG_RELOAD_UNUSED = 0, 41 | GLB_CONTROL_MSG_RELOAD_CONFIG = 1, 42 | } glb_processor_control_msg_cmd; 43 | 44 | struct glb_processor_control_msg { 45 | glb_processor_control_msg_cmd cmd; 46 | 47 | union { 48 | struct { 49 | struct glb_fwd_config_ctx *new_config_ctx; 50 | } reload_msg; 51 | }; 52 | }; 53 | 54 | /* 55 | * total_packet_count == ( 56 | director_packet_count + classification_failures + eth_rx_errors + 57 | kni_packet_count 58 | ) 59 | * director_packet_count == ( 60 | encap_successes + encap_failures 61 | ) 62 | * director_packet_count == eth_tx_packets_sent 63 | * kni_packet_count == kni_tx_packets_sent 64 | */ 65 | struct processor_metrics { 66 | rte_atomic64_t total_packet_count; 67 | rte_atomic64_t director_packet_count; 68 | rte_atomic64_t classification_failures; 69 | rte_atomic64_t eth_rx_errors; 70 | rte_atomic64_t kni_packet_count; 71 | rte_atomic64_t encap_failures; 72 | rte_atomic64_t encap_successes; 73 | rte_atomic64_t eth_tx_packets_sent; 74 | rte_atomic64_t kni_tx_packets_sent; 75 | rte_atomic64_t reload_count; 76 | } __rte_cache_aligned; 77 | 78 | struct glb_processor_ctx { 79 | struct glb_fwd_config_ctx *config_ctx; 80 | struct rte_ring *control_msg_ring; 81 | 82 | unsigned int num_ports; 83 | 84 | // notification flags for this core 85 | rte_atomic32_t director_stop; 86 | 87 | // metrics for this core 88 | struct processor_metrics metrics; 89 | 90 | glb_director_lcore_config lcore_config; 91 | 92 | // distributor used by both dist and worker workloads 93 | struct rte_distributor *dist; 94 | // for workers, their worker ID (unique, sequential from 0) 95 | unsigned int dist_worker_id; 96 | }; 97 | 98 | int main_loop_processor(void *arg); 99 | -------------------------------------------------------------------------------- /src/glb-director/packaging/.gitignore: -------------------------------------------------------------------------------- 1 | forwarding_table.bin 2 | -------------------------------------------------------------------------------- /src/glb-director/packaging/director.conf: -------------------------------------------------------------------------------- 1 | { 2 | "outbound_gateway_mac": "00:11:22:33:44:55", 3 | "outbound_src_ip": "1.2.3.4", 4 | "forward_icmp_ping_responses": true, 5 | "num_worker_queues": 1, 6 | "flow_paths": [ 7 | { "rx_port": 0, "rx_queue": 0, "tx_port": 0, "tx_queue": 0 } 8 | ], 9 | "lcores": { 10 | "lcore-5": { 11 | "rx": true, 12 | "tx": true, 13 | "flow_paths": [0], 14 | 15 | "dist": true, 16 | "num_dist_workers": 1, 17 | 18 | "kni": true 19 | }, 20 | "lcore-6": { 21 | "work": true, 22 | "work_source": 5 23 | }, 24 | "lcore-7": { 25 | "work": true, 26 | "work_source": 5 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/glb-director/packaging/forwarding_table.json: -------------------------------------------------------------------------------- 1 | { 2 | "tables": [] 3 | } 4 | -------------------------------------------------------------------------------- /src/glb-director/packaging/glb-director: -------------------------------------------------------------------------------- 1 | GLB_DIRECTOR_EAL_ARGS="--master-lcore 4 -l 4,5,6,7" 2 | GLB_DIRECTOR_CONFIG_FILE="/etc/glb/director.conf" 3 | GLB_DIRECTOR_FORWARDING_TABLE="/etc/glb/forwarding_table.bin" 4 | -------------------------------------------------------------------------------- /src/glb-director/packaging/glb-director.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=GLB Director 3 | After=network.target network-online.target 4 | Wants=network-online.target 5 | 6 | [Service] 7 | # Allow the service to notify systemd when it has finished activating. 8 | Type=notify 9 | # NotifyAccess will allow the main pid to send the above ready message (which is also the default). 10 | NotifyAccess=main 11 | Restart=always 12 | EnvironmentFile=/etc/default/glb-director 13 | ExecStart=/usr/sbin/glb-director $GLB_DIRECTOR_EAL_ARGS -- --config-file ${GLB_DIRECTOR_CONFIG_FILE} --forwarding-table ${GLB_DIRECTOR_FORWARDING_TABLE} 14 | ExecReload=/bin/kill -USR1 $MAINPID 15 | TimeoutStopSec=3 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /src/glb-director/packaging/version.sh: -------------------------------------------------------------------------------- 1 | GLB_DIRECTOR_VERSION="1.0.12" 2 | -------------------------------------------------------------------------------- /src/glb-director/script/create-packages: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # BSD 3-Clause License 4 | # 5 | # Copyright (c) 2018 GitHub. 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # * Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from 20 | # this software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | set -e 34 | ROOTDIR=$(dirname $0)/.. 35 | cd $ROOTDIR 36 | 37 | . packaging/version.sh 38 | 39 | make clean 40 | make -C cli clean 41 | 42 | make 43 | make -C cli 44 | 45 | ./cli/glb-director-cli build-config packaging/forwarding_table.json packaging/forwarding_table.bin 46 | 47 | fpm -f -s dir -t deb \ 48 | -n glb-director-cli \ 49 | -v ${GLB_DIRECTOR_VERSION} \ 50 | -d 'libjansson4' \ 51 | --license 'BSD 3-Clause' \ 52 | --maintainer 'GitHub ' \ 53 | cli/glb-director-cli=/usr/sbin/ \ 54 | cli/glb-config-check=/usr/sbin/ 55 | 56 | fpm -f -s dir -t deb \ 57 | -n glb-director \ 58 | -v ${GLB_DIRECTOR_VERSION} \ 59 | -d 'dpdk = 17.11.1-6' \ 60 | -d 'libjansson4' \ 61 | -d "glb-director-cli = ${GLB_DIRECTOR_VERSION}" \ 62 | --conflicts 'glb-director-xdp' \ 63 | --license 'BSD 3-Clause' \ 64 | --maintainer 'GitHub ' \ 65 | --deb-systemd packaging/glb-director.service \ 66 | --config-files /etc \ 67 | build/app/glb-director=/usr/sbin/ \ 68 | packaging/director.conf=/etc/glb/ \ 69 | packaging/forwarding_table.bin=/etc/glb/ \ 70 | packaging/glb-director=/etc/default/ 71 | 72 | if [ -d "$BUILDDIR" ]; then 73 | cp glb-director_${GLB_DIRECTOR_VERSION}_amd64.deb $BUILDDIR/ 74 | cp glb-director-cli_${GLB_DIRECTOR_VERSION}_amd64.deb $BUILDDIR/ 75 | fi 76 | 77 | make clean 78 | make -C cli clean 79 | -------------------------------------------------------------------------------- /src/glb-director/script/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # BSD 3-Clause License 4 | # 5 | # Copyright (c) 2018 GitHub. 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # * Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from 20 | # this software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | set -e 34 | 35 | export BASEDIR=$(cd $(dirname "$0") && cd .. && pwd) 36 | cd "$(dirname "$0")/.." 37 | 38 | . ../../script/helpers/folding.sh 39 | 40 | begin_fold "Building glb-director for testing" 41 | ( 42 | make clean 43 | make -C cli clean 44 | 45 | scan-build-10 make 46 | scan-build-10 make -C cli 47 | ) 48 | end_fold 49 | 50 | begin_fold "Running scapy packet tests against glb-director" 51 | ( 52 | PYTHONPATH=$(pwd)/../scapy-glb-gue/:$PYTHONPATH nosetests -v -a '!director_type' -a 'director_type=dpdk' 53 | ) 54 | end_fold 55 | 56 | begin_fold "Running glb-director config tests" 57 | ( 58 | bash tests/config_check.sh 59 | ) 60 | end_fold 61 | 62 | begin_fold "Running pcap tests" 63 | ( 64 | # needs hugepages run after other tests since its already set up 65 | bash tests/pcap_tests.sh 66 | ) 67 | end_fold 68 | 69 | begin_fold "valgrind tests" 70 | ( 71 | bash tests/valgrind_check.sh 72 | ) 73 | end_fold 74 | 75 | begin_fold "stub server tests" 76 | ( 77 | bash tests/stub_server_tests.sh 78 | ) 79 | end_fold 80 | -------------------------------------------------------------------------------- /src/glb-director/shared_opt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #include "shared_opt.h" 34 | #include 35 | 36 | /* parses --config-file, --forwarding-table, and --debug cli options */ 37 | 38 | void get_options(char *config_file, char *forwarding_table, int argc, 39 | char *const *argv) 40 | { 41 | 42 | int opt_index, opt; 43 | debug = false; 44 | 45 | static struct option long_options[] = { 46 | {"config-file", required_argument, NULL, 'c'}, 47 | {"forwarding-table", required_argument, NULL, 't'}, 48 | {"debug", no_argument, NULL, 'v'}, 49 | {NULL, 0, NULL, 0}}; 50 | 51 | while ((opt = getopt_long(argc, argv, ":c:t:v", long_options, NULL)) != 52 | -1) 53 | switch (opt) { 54 | case 'c': 55 | strcpy(config_file, optarg); 56 | break; 57 | case 't': 58 | strcpy(forwarding_table, optarg); 59 | break; 60 | case 'v': 61 | debug = true; 62 | break; 63 | case ':': 64 | /* missing option argument */ 65 | glb_log_error("%s: option '-%c' requires an argument", 66 | argv[0], optopt); 67 | GLB_FALL_THROUGH; 68 | case '?': 69 | /* invalid option */ 70 | glb_log_error("Invalid option(s) in command"); 71 | GLB_FALL_THROUGH; 72 | default: 73 | abort(); 74 | } 75 | 76 | glb_log_info("Using config: %s, Using forwarding table: %s,", 77 | config_file, forwarding_table); 78 | 79 | for (opt_index = optind; opt_index < argc; opt_index++) 80 | glb_log_error("Non-option argument %s", argv[opt_index]); 81 | }; 82 | -------------------------------------------------------------------------------- /src/glb-director/shared_opt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef SHARED_OPT 34 | #define SHARED_OPT 35 | 36 | #include "log.h" 37 | #include 38 | 39 | extern bool debug; 40 | 41 | /* parses --config-file, --forwarding-table, and --debug cli options */ 42 | 43 | void get_options(char *config_file, char *forwarding_table, int argc, 44 | char *const *argv); 45 | 46 | #if defined(__GNUC__) && __GNUC__ >= 7 47 | #define GLB_FALL_THROUGH __attribute__ ((fallthrough)) 48 | #else 49 | #define GLB_FALL_THROUGH ((void)0) 50 | #endif /* __GNUC__ >= 7 */ 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/glb-director/siphash24.h: -------------------------------------------------------------------------------- 1 | /* 2 | SipHash reference C implementation 3 | 4 | Copyright (c) 2012-2014 Jean-Philippe Aumasson 5 | Copyright (c) 2012-2014 Daniel J. Bernstein 6 | 7 | 8 | To the extent possible under law, the author(s) have dedicated all copyright 9 | and related and neighboring rights to this software to the public domain 10 | worldwide. This software is distributed without any warranty. 11 | 12 | You should have received a copy of the CC0 Public Domain Dedication along 13 | with this software. If not, see 14 | . 15 | */ 16 | 17 | int siphash(uint8_t *out, const uint8_t *in, uint64_t inlen, const uint8_t *k); 18 | -------------------------------------------------------------------------------- /src/glb-director/statsd-client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Originally from: https://github.com/romanbsd/statsd-c-client 3 | * 4 | * Copyright (c) 2012 Roman Shterenzon 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the 8 | * "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #define _H_STATSD_CLIENT 27 | #include 28 | #include 29 | #include 30 | 31 | struct _statsd_link { 32 | struct sockaddr_in server; 33 | int sock; 34 | char *ns; 35 | }; 36 | 37 | typedef struct _statsd_link statsd_link; 38 | 39 | statsd_link *statsd_init(const char *host, int port); 40 | statsd_link *statsd_init_with_namespace(const char *host, int port, 41 | const char *ns); 42 | void statsd_finalize(statsd_link *link); 43 | 44 | /* 45 | write the stat line to the provided buffer, 46 | type can be "c", "g" or "ms" 47 | lf - whether line feed needs to be added 48 | */ 49 | void statsd_prepare(statsd_link *link, const char *stat, size_t value, 50 | const char *type, float sample_rate, char *buf, 51 | size_t buflen, int lf, char *tag); 52 | 53 | /* manually send a message, which might be composed of several lines. Must be 54 | * null-terminated */ 55 | int statsd_send(statsd_link *link, const char *message); 56 | 57 | int statsd_inc(statsd_link *link, const char *stat, float sample_rate, char *tag); 58 | int statsd_dec(statsd_link *link, const char *stat, float sample_rate, char *tag); 59 | int statsd_count(statsd_link *link, const char *stat, size_t count, float sample_rate, 60 | char *tag); 61 | int statsd_gauge(statsd_link *link, const char *stat, size_t value, char *tag); 62 | int statsd_timing(statsd_link *link, const char *stat, size_t ms, char *tag); 63 | -------------------------------------------------------------------------------- /src/glb-director/strlcpy.h: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1998 Todd C. Miller 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | /* 20 | * Copy src to string dst of size siz. At most siz-1 characters 21 | * will be copied. Always NUL terminates (unless siz == 0). 22 | * Returns strlen(src); if retval >= siz, truncation occurred. 23 | */ 24 | static inline size_t 25 | strlcpy(char * __restrict dst, const char * __restrict src, size_t siz) 26 | { 27 | char *d = dst; 28 | const char *s = src; 29 | size_t n = siz; 30 | 31 | /* Copy as many bytes as will fit */ 32 | if (n != 0) { 33 | while (--n != 0) { 34 | if ((*d++ = *s++) == '\0') 35 | break; 36 | } 37 | } 38 | 39 | /* Not enough room in dst, add NUL and traverse rest of src */ 40 | if (n == 0) { 41 | if (siz != 0) 42 | *d = '\0'; /* NUL-terminate dst */ 43 | while (*s++) 44 | ; 45 | } 46 | 47 | return(s - src - 1); /* count does not include NUL */ 48 | } 49 | -------------------------------------------------------------------------------- /src/glb-director/tests/config_check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # BSD 3-Clause License 4 | # 5 | # Copyright (c) 2018 GitHub. 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # * Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from 20 | # this software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | set -eo pipefail 34 | 35 | . "$BASEDIR/tests/lib/testlib.sh" 36 | 37 | begin_test "config checker exits cleanly" 38 | ( 39 | $BASEDIR/cli/glb-director-cli build-config \ 40 | $BASEDIR/tests/data/table.json \ 41 | $BASEDIR/tests/data/test-tables.bin 42 | 43 | sudo $BASEDIR/cli/glb-config-check --no-huge -- \ 44 | --config-file $BASEDIR/tests/data/config.json \ 45 | --forwarding-table $BASEDIR/tests/data/test-tables.bin 2>&1 \ 46 | | tee $BASEDIR/build/check.out 47 | ) 48 | end_test 49 | 50 | begin_test "config checker returns ok" 51 | ( 52 | grep 'Config ok' $BASEDIR/build/check.out 53 | ) 54 | end_test 55 | 56 | begin_test "bind get classified" 57 | ( 58 | grep 'Creating ICMP fragmentation needed bind classifier: 1.1.1.1' $BASEDIR/build/check.out 59 | ) 60 | end_test 61 | 62 | begin_test "bind gets outputted" 63 | ( 64 | grep 'bind: 1.1.1.1:\[80-80\] (6)' $BASEDIR/build/check.out 65 | ) 66 | end_test 67 | 68 | begin_test "backend gets outputted" 69 | ( 70 | grep '** backend: 1.2.3.4' $BASEDIR/build/check.out 71 | ) 72 | end_test 73 | 74 | begin_test "no errors" 75 | ( 76 | grep -iv 'failed' $BASEDIR/build/check.out 77 | ) 78 | end_test 79 | -------------------------------------------------------------------------------- /src/glb-director/tests/data/1k_pkts.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/src/glb-director/tests/data/1k_pkts.pcap -------------------------------------------------------------------------------- /src/glb-director/tests/data/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "outbound_src_ip": "65.65.65.65", 3 | "outbound_gateway_mac": "3a:89:7c:7b:5d:1f", 4 | "num_worker_queues": 1, 5 | "flow_paths": [ 6 | { "rx_port": 0, "rx_queue": 0, "tx_port": 0, "tx_queue": 0 } 7 | ], 8 | "lcores": { 9 | "lcore-1": { 10 | "rx": true, 11 | "tx": true, 12 | "flow_paths": [0], 13 | "dist": true, 14 | "num_dist_workers": 1 15 | }, 16 | "lcore-2": { 17 | "work": true, 18 | "work_source": 1 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/glb-director/tests/data/dummy1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/glb-director/a33a84c67db31d2eb5c5630931f45e93dfb886c0/src/glb-director/tests/data/dummy1.bin -------------------------------------------------------------------------------- /src/glb-director/tests/data/table.json: -------------------------------------------------------------------------------- 1 | { 2 | "tables": [ 3 | { 4 | "hash_key": "12345678901234561234567890123456", 5 | "seed": "34567890123456783456789012345678", 6 | "binds": [ 7 | { "ip": "1.1.1.1", "proto": "tcp", "port": 80 }, 8 | { "ip": "1.1.1.1", "proto": "tcp", "port": 443 } 9 | ], 10 | "backends": [ 11 | { "ip": "1.2.3.4", "state": "active", "healthy": true }, 12 | { "ip": "2.3.4.5", "state": "active", "healthy": true }, 13 | { "ip": "3.4.5.6", "state": "active", "healthy": true } 14 | ] 15 | }, 16 | { 17 | "hash_key": "12345678901234561234567890123456", 18 | "seed": "12345678901234561234567890123456", 19 | "binds": [ 20 | { "ip": "1.1.1.2", "proto": "tcp", "port": 80 }, 21 | { "ip": "1.1.1.3", "proto": "tcp", "port": 80 }, 22 | { "ip": "fdb4:98ce:52d4::42", "proto": "tcp", "port": 80 } 23 | ], 24 | "backends": [ 25 | { "ip": "4.5.6.7", "state": "active", "healthy": true }, 26 | { "ip": "5.6.7.8", "state": "active", "healthy": true }, 27 | { "ip": "6.7.8.9", "state": "active", "healthy": true }, 28 | { "ip": "7.8.9.0", "state": "active", "healthy": true } 29 | ] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /src/glb-director/tests/data/table1.json: -------------------------------------------------------------------------------- 1 | { 2 | "tables": [ 3 | { 4 | "hash_key": "12345678901234561234567890123456", 5 | "seed": "34567890123456783456789012345678", 6 | "binds": [ 7 | { "ip": "1.1.1.1", "proto": "tcp", "port": 80 }, 8 | { "ip": "1.1.1.1", "proto": "tcp", "port": 443 } 9 | ], 10 | "backends": [ 11 | { "ip": "2.3.4.5", "state": "active", "healthy": true }, 12 | { "ip": "3.4.5.6", "state": "active", "healthy": true } 13 | ] 14 | }, 15 | { 16 | "hash_key": "12345678901234561234567890123456", 17 | "seed": "12345678901234561234567890123456", 18 | "binds": [ 19 | { "ip": "1.1.1.2", "proto": "tcp", "port": 80 }, 20 | { "ip": "1.1.1.3", "proto": "tcp", "port": 80 }, 21 | { "ip": "fdb4:98ce:52d4::42", "proto": "tcp", "port": 80 } 22 | ], 23 | "backends": [ 24 | { "ip": "4.5.6.7", "state": "active", "healthy": true }, 25 | { "ip": "5.6.7.8", "state": "active", "healthy": true }, 26 | { "ip": "6.7.8.9", "state": "active", "healthy": true }, 27 | { "ip": "7.8.9.0", "state": "active", "healthy": true } 28 | ] 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /src/glb-director/tests/data/table2.json: -------------------------------------------------------------------------------- 1 | { 2 | "tables": [ 3 | { 4 | "hash_key": "12345678901234561234567890123456", 5 | "seed": "34567890123456783456789012345678", 6 | "binds": [ 7 | { "ip": "1.1.1.1", "proto": "tcp", "port": 80 }, 8 | { "ip": "1.1.1.1", "proto": "tcp", "port": 443 } 9 | ], 10 | "backends": [ 11 | { "ip": "1.2.3.4", "state": "active", "healthy": true }, 12 | { "ip": "2.3.4.5", "state": "active", "healthy": true }, 13 | { "ip": "3.4.5.6", "state": "draining", "healthy": true } 14 | ] 15 | }, 16 | { 17 | "hash_key": "12345678901234561234567890123456", 18 | "seed": "12345678901234561234567890123456", 19 | "binds": [ 20 | { "ip": "1.1.1.2", "proto": "tcp", "port": 80 }, 21 | { "ip": "1.1.1.3", "proto": "tcp", "port": 80 }, 22 | { "ip": "fdb4:98ce:52d4::42", "proto": "tcp", "port": 80 } 23 | ], 24 | "backends": [ 25 | { "ip": "4.5.6.7", "state": "active", "healthy": true }, 26 | { "ip": "5.6.7.8", "state": "active", "healthy": true }, 27 | { "ip": "6.7.8.9", "state": "active", "healthy": true }, 28 | { "ip": "7.8.9.0", "state": "active", "healthy": true } 29 | ] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /src/glb-director/tests/data/table3.json: -------------------------------------------------------------------------------- 1 | { 2 | "tables": [ 3 | { 4 | "hash_key": "12345678901234561234567890123456", 5 | "seed": "34567890123456783456789012345678", 6 | "binds": [ 7 | { "ip": "1.1.1.1", "proto": "tcp", "port": 80 }, 8 | { "ip": "1.1.1.1", "proto": "tcp", "port": 443 } 9 | ], 10 | "backends": [ 11 | { "ip": "1.2.3.4", "state": "active", "healthy": true }, 12 | { "ip": "2.3.4.5", "state": "active", "healthy": true }, 13 | { "ip": "3.4.5.6", "state": "active", "healthy": false } 14 | ] 15 | }, 16 | { 17 | "hash_key": "12345678901234561234567890123456", 18 | "seed": "12345678901234561234567890123456", 19 | "binds": [ 20 | { "ip": "1.1.1.2", "proto": "tcp", "port": 80 }, 21 | { "ip": "1.1.1.3", "proto": "tcp", "port": 80 }, 22 | { "ip": "fdb4:98ce:52d4::42", "proto": "tcp", "port": 80 } 23 | ], 24 | "backends": [ 25 | { "ip": "4.5.6.7", "state": "active", "healthy": true }, 26 | { "ip": "5.6.7.8", "state": "active", "healthy": true }, 27 | { "ip": "6.7.8.9", "state": "active", "healthy": true }, 28 | { "ip": "7.8.9.0", "state": "active", "healthy": true } 29 | ] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /src/glb-director/tests/lib/testlib.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Usage: . testlib.sh 3 | # Simple shell command language test library. 4 | # 5 | # Tests must follow the basic form: 6 | # 7 | # begin_test "the thing" 8 | # ( 9 | # set -e 10 | # echo "hello" 11 | # false 12 | # ) 13 | # end_test 14 | # 15 | # When a test fails its stdout and stderr are shown. 16 | # 17 | # Note that tests must `set -e' within the subshell block or failed assertions 18 | # will not cause the test to fail and the result may be misreported. 19 | # 20 | # Copyright (c) 2011-13 by Ryan Tomayko 21 | # License: MIT 22 | set -e 23 | 24 | # Put bin path on PATH 25 | PATH="$(cd $(dirname "$0")/.. && pwd)/bin:$PATH" 26 | 27 | # create a temporary work space 28 | TMPDIR="$(cd $(dirname "$0")/.. && pwd)"/tmp 29 | TRASHDIR="$TMPDIR/$(basename "$0")-$$" 30 | 31 | # keep track of num tests and failures 32 | tests=0 33 | failures=0 34 | 35 | # this runs at process exit 36 | atexit () { 37 | rm -rf "$TRASHDIR" 38 | if [ $failures -gt 0 ] 39 | then exit 1 40 | else exit 0 41 | fi 42 | } 43 | 44 | # create the trash dir 45 | trap "atexit" EXIT 46 | mkdir -p "$TRASHDIR" 47 | cd "$TRASHDIR" 48 | 49 | # Mark the beginning of a test. A subshell should immediately follow this 50 | # statement. 51 | begin_test () { 52 | test_status=$? 53 | [ -n "$test_description" ] && end_test $test_status 54 | unset test_status 55 | 56 | tests=$(( tests + 1 )) 57 | test_description="$1" 58 | 59 | exec 3>&1 4>&2 60 | out="$TRASHDIR/out" 61 | err="$TRASHDIR/err" 62 | exec 1>"$out" 2>"$err" 63 | 64 | # allow the subshell to exit non-zero without exiting this process 65 | set -x +e 66 | } 67 | 68 | # Mark the end of a test. 69 | end_test () { 70 | test_status="${1:-$?}" 71 | set +x -e 72 | exec 1>&3 2>&4 73 | 74 | if [ "$test_status" -eq 0 ]; then 75 | printf "test: %-60s OK\n" "$test_description ..." 76 | else 77 | failures=$(( failures + 1 )) 78 | printf "test: %-60s FAILED\n" "$test_description ..." 79 | ( 80 | echo "-- stdout --" 81 | sed 's/^/ /' <"$TRASHDIR/out" 82 | echo "-- stderr --" 83 | grep -v -e '^\+ end_test' -e '^+ set +x' <"$TRASHDIR/err" | 84 | sed 's/^/ /' 85 | ) 1>&2 86 | fi 87 | unset test_description 88 | } 89 | 90 | end_test_exfail () { 91 | end_test $? 1 92 | } 93 | -------------------------------------------------------------------------------- /src/glb-director/tests/pcap_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # BSD 3-Clause License 4 | # 5 | # Copyright (c) 2018 GitHub. 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # * Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from 20 | # this software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | set -e 34 | 35 | . "$BASEDIR/tests/lib/testlib.sh" 36 | 37 | begin_test "run with pcap and example tables" 38 | ( 39 | $BASEDIR/cli/glb-director-cli build-config \ 40 | $BASEDIR/tests/data/table.json \ 41 | $BASEDIR/tests/data/test-tables.bin 42 | 43 | sudo timeout 2.0 $BASEDIR/build/glb-director \ 44 | --vdev="net_pcap0,rx_pcap=$BASEDIR/tests/data/1k_pkts.pcap,tx_pcap=$BASEDIR/build/tx.pcap" -- \ 45 | --config-file $BASEDIR/tests/data/config.json \ 46 | --forwarding-table $BASEDIR/tests/data/test-tables.bin \ 47 | || true # timeout will make this look like an error, but it's expected 48 | ) 49 | end_test 50 | 51 | begin_test "tx: should be 1000 packets" 52 | ( 53 | sudo tcpdump -r $BASEDIR/build/tx.pcap | wc -l | grep 1000 54 | ) 55 | end_test 56 | 57 | begin_test "tx: verify to/from" 58 | ( 59 | sudo tcpdump -nr $BASEDIR/build/tx.pcap | grep -q 'IP 65.65.65.65.61139 > 3.4.5.6.19523: UDP, length 52' 60 | ) 61 | end_test 62 | -------------------------------------------------------------------------------- /src/glb-director/tests/rendezvous_table.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 GitHub. 2 | # 3 | # This file is part of the `glb-director` test suite. 4 | # 5 | # This file is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This file is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this project. If not, see . 17 | 18 | import struct, siphash, socket 19 | 20 | class GLBRendezvousTable(object): 21 | def __init__(self, seed_bytes): 22 | self.seed_bytes = seed_bytes 23 | 24 | def calculate_forwarding_table_row_seed(self, index): 25 | index_bytes = struct.pack('>I', index) 26 | return siphash.SipHash_2_4(self.seed_bytes, index_bytes).digest() 27 | 28 | def forwarding_table_entry(self, index, hosts): 29 | row_seed = self.calculate_forwarding_table_row_seed(index) 30 | 31 | sorter = lambda ip: int(siphash.SipHash_2_4(self.seed_bytes, row_seed + socket.inet_aton(ip)).hexdigest(), 16) 32 | 33 | copy = hosts[:] 34 | copy.sort(key=sorter) 35 | return copy 36 | -------------------------------------------------------------------------------- /src/glb-director/tests/test-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "tables": [ 3 | { 4 | "binds": [ 5 | { 6 | "ip": "1.1.1.1", 7 | "port": 80, 8 | "proto": "tcp" 9 | }, 10 | { 11 | "ip": "1.1.1.1", 12 | "port": 443, 13 | "proto": "tcp" 14 | } 15 | ], 16 | "seed": "34567890123456783456789012345678", 17 | "hash_key": "12345678901234561234567890123456", 18 | "backends": [ 19 | { 20 | "healthy": true, 21 | "ip": "1.2.3.4", 22 | "state": "active" 23 | }, 24 | { 25 | "healthy": true, 26 | "ip": "2.3.4.5", 27 | "state": "active" 28 | }, 29 | { 30 | "healthy": true, 31 | "ip": "3.4.5.6", 32 | "state": "active" 33 | } 34 | ] 35 | }, 36 | { 37 | "binds": [ 38 | { 39 | "ip": "1.1.1.2", 40 | "port": 80, 41 | "proto": "tcp" 42 | }, 43 | { 44 | "ip": "1.1.1.3", 45 | "port": 80, 46 | "proto": "tcp" 47 | }, 48 | { 49 | "ip": "fdb4:98ce:52d4::42", 50 | "port": 80, 51 | "proto": "tcp" 52 | } 53 | ], 54 | "seed": "12345678901234561234567890123456", 55 | "hash_key": "12345678901234561234567890123456", 56 | "backends": [ 57 | { 58 | "healthy": true, 59 | "ip": "4.5.6.7", 60 | "state": "active" 61 | }, 62 | { 63 | "healthy": true, 64 | "ip": "5.6.7.8", 65 | "state": "active" 66 | }, 67 | { 68 | "healthy": true, 69 | "ip": "6.7.8.9", 70 | "state": "active" 71 | }, 72 | { 73 | "healthy": true, 74 | "ip": "7.8.9.0", 75 | "state": "active" 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | -------------------------------------------------------------------------------- /src/glb-director/tests/test_director_hash_fields.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 GitHub. 2 | # 3 | # This file is part of the `glb-director` test suite. 4 | # 5 | # This file is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This file is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this project. If not, see . 17 | 18 | from glb_test_utils import GLBDirectorTestBase, GLBGUE 19 | from scapy.all import Ether, IP, IPv6, Packet, UDP, TCP, ICMP 20 | from nose.tools import assert_equals 21 | import socket, struct, time 22 | 23 | class GLBHashFieldsBase(GLBDirectorTestBase): 24 | alt_route_fields = None 25 | 26 | @classmethod 27 | def get_initial_director_config(cls): 28 | base_cfg = GLBDirectorTestBase.get_initial_director_config() 29 | base_cfg.update(cls.config_ext) 30 | return base_cfg 31 | 32 | def test_01_route_classified_v4(self): 33 | for ip_kwargs, tcp_kwargs, expected_route in self.expected_routes: 34 | test_packet = Ether()/IP(**ip_kwargs)/TCP(**tcp_kwargs) 35 | self.sendp(test_packet, iface=self.IFACE_NAME_PY) 36 | 37 | route_path = self.route_for_packet(test_packet, fields=self.route_fields) 38 | if self.alt_route_fields is not None: 39 | route_path.extend(self.route_for_packet(test_packet, fields=self.alt_route_fields)) 40 | assert_equals(route_path, expected_route) 41 | 42 | packet = self.wait_for_packet(self.eth_tx, lambda packet: isinstance(packet.payload, IP) and packet.payload.dst == route_path[0]) 43 | 44 | assert isinstance(packet, Ether) 45 | assert_equals(packet.dst, self.py_side_mac) 46 | 47 | fou_ip = packet.payload 48 | assert isinstance(fou_ip, IP) # Expecting an IP packet 49 | assert_equals(fou_ip.src, '65.65.65.65') 50 | assert_equals(fou_ip.dst, route_path[0]) 51 | 52 | fou_udp = fou_ip.payload 53 | assert isinstance(fou_udp, UDP) # Expecting a FOU packet 54 | assert_equals(fou_udp.sport, self.sport_for_packet(test_packet, fields=self.route_fields)) 55 | assert_equals(fou_udp.dport, self.DIRECTOR_GUE_PORT) 56 | 57 | glb_gue = fou_udp.payload 58 | assert isinstance(glb_gue, GLBGUE) # Expecting a GUE packet (scapy will always map this) 59 | assert_equals(glb_gue.private_data[0].hop_count, len(route_path) - 1) 60 | assert_equals(glb_gue.private_data[0].next_hop, 0) 61 | assert_equals(glb_gue.private_data[0].hops, route_path[1:]) 62 | 63 | class TestGLBHashFieldsSourceAddr(GLBHashFieldsBase): 64 | config_ext = { 65 | 'hash_fields': { 'src_addr': True }, 66 | } 67 | route_fields = ('src_addr',) 68 | expected_routes = [ 69 | ({'src': '10.11.12.13', 'dst': '1.1.1.1'}, {'sport': 45678, 'dport': 80}, ['3.4.5.6', '2.3.4.5']), 70 | ({'src': '10.11.12.13', 'dst': '1.1.1.1'}, {'sport': 45679, 'dport': 80}, ['3.4.5.6', '2.3.4.5']), 71 | ({'src': '10.11.12.13', 'dst': '1.1.1.1'}, {'sport': 45680, 'dport': 80}, ['3.4.5.6', '2.3.4.5']), 72 | ] 73 | 74 | class TestGLBHashFieldsSourceAddrAndPort(GLBHashFieldsBase): 75 | config_ext = { 76 | 'hash_fields': { 'src_addr': True, 'src_port': True }, 77 | } 78 | route_fields = ('src_addr', 'src_port') 79 | expected_routes = [ 80 | ({'src': '10.11.12.13', 'dst': '1.1.1.1'}, {'sport': 45678, 'dport': 80}, ['1.2.3.4', '2.3.4.5']), 81 | ({'src': '10.11.12.13', 'dst': '1.1.1.1'}, {'sport': 45679, 'dport': 80}, ['1.2.3.4', '3.4.5.6']), 82 | ({'src': '10.11.12.13', 'dst': '1.1.1.1'}, {'sport': 45680, 'dport': 80}, ['2.3.4.5', '3.4.5.6']), 83 | ] 84 | 85 | class TestGLBHashFieldsMigration(GLBHashFieldsBase): 86 | config_ext = { 87 | 'hash_fields': { 'src_addr': True, 'src_port': True }, 88 | 'alt_hash_fields': { 'src_addr': True }, 89 | } 90 | route_fields = ('src_addr', 'src_port') 91 | alt_route_fields = ('src_addr',) 92 | expected_routes = [ 93 | ({'src': '10.11.12.13', 'dst': '1.1.1.1'}, {'sport': 45678, 'dport': 80}, ['1.2.3.4', '2.3.4.5', '3.4.5.6', '2.3.4.5']), 94 | ({'src': '10.11.12.13', 'dst': '1.1.1.1'}, {'sport': 45679, 'dport': 80}, ['1.2.3.4', '3.4.5.6', '3.4.5.6', '2.3.4.5']), 95 | ({'src': '10.11.12.13', 'dst': '1.1.1.1'}, {'sport': 45680, 'dport': 80}, ['2.3.4.5', '3.4.5.6', '3.4.5.6', '2.3.4.5']), 96 | ] 97 | -------------------------------------------------------------------------------- /src/glb-director/tests/test_director_kni.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 GitHub. 2 | # 3 | # This file is part of the `glb-director` test suite. 4 | # 5 | # This file is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This file is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this project. If not, see . 17 | 18 | from glb_test_utils import GLBDirectorTestBase, GLBGUE 19 | from scapy.all import Ether, IP, IPv6, Packet, UDP, TCP 20 | from nose.tools import assert_equals 21 | from nose.plugins.attrib import attr 22 | 23 | @attr(director_type='dpdk') 24 | class TestGLBKNI(GLBDirectorTestBase): 25 | def test_01_nic_rx_to_kni(self): 26 | if self.kni_tx is None: return # if no KNI is available, don't test 27 | 28 | self.sendp(Ether()/IP(dst="1.2.3.4"), iface=self.IFACE_NAME_PY) 29 | packet = self.wait_for_packet(self.kni_tx, lambda packet: isinstance(packet.payload, IP) and packet.payload.dst == '1.2.3.4') 30 | assert_equals(packet.payload.dst, '1.2.3.4') 31 | 32 | def test_02_kni_to_nic_tx(self): 33 | if self.kni_tx is None: return # if no KNI is available, don't test 34 | 35 | self.sendp(Ether()/IP(dst="1.2.3.5"), iface=self.IFACE_NAME_KNI) 36 | packet = self.wait_for_packet(self.eth_tx, lambda packet: isinstance(packet.payload, IP) and packet.payload.dst == '1.2.3.5') 37 | assert_equals(packet.payload.dst, '1.2.3.5') 38 | -------------------------------------------------------------------------------- /src/glb-director/tests/test_director_metrics.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 GitHub. 2 | # 3 | # This file is part of the `glb-director` test suite. 4 | # 5 | # This file is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This file is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this project. If not, see . 17 | 18 | from glb_test_utils import GLBDirectorTestBase, GLBGUE 19 | from scapy.all import Ether, IP, IPv6, Packet, UDP, TCP, ICMP 20 | from nose.tools import assert_equals 21 | from nose.plugins.attrib import attr 22 | import socket, struct, time 23 | 24 | @attr(director_type='xdp') 25 | class TestGLBDirectorMetrics(GLBDirectorTestBase): 26 | def test_01_route_classified_increments_metrics(self): 27 | self.clear_metrics() 28 | 29 | test_packet = Ether(dst='56:0e:37:46:a2:21', src='b6:59:5f:11:c1:2a')/IP(src="10.11.12.13", dst="1.1.1.1")/TCP(sport=45678, dport=80) 30 | self.sendp(test_packet, iface=self.IFACE_NAME_PY) 31 | packet = self.wait_for_packet(self.eth_tx, lambda packet: isinstance(packet.payload, IP) and packet.payload.dst == '3.4.5.6') 32 | 33 | time.sleep(10) # wait for 1 metrics cycle 34 | 35 | self.expect_metrics({ 36 | ('glb.director.packets.results', ('glb_engine:xdp', 'result:Matched')): (lambda value: value > 0), 37 | ('glb.director.packets.results', ('glb_engine:xdp', 'result:UnknownFormat')): (lambda value: value == 0), 38 | ('glb.director.packets.processed', ('glb_engine:xdp',)): (lambda value: value > 0), 39 | ('glb.director.packets.encapsulated', ('glb_engine:xdp',)): (lambda value: value > 0), 40 | }) 41 | -------------------------------------------------------------------------------- /src/glb-director/tests/test_rendezvous_table.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 GitHub. 2 | # 3 | # This file is part of the `glb-director` test suite. 4 | # 5 | # This file is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This file is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this project. If not, see . 17 | 18 | from rendezvous_table import GLBRendezvousTable 19 | from nose.tools import assert_equals 20 | 21 | class TestGLBRendezvousTable(): 22 | def test_row_seeds(self): 23 | """GLBRendezvousTable correctly calculates valid row seeds""" 24 | 25 | forwarding_table_seed = '49a3d861d661ae5ab06ed9326871a2f5'.decode('hex') 26 | table = GLBRendezvousTable(forwarding_table_seed) 27 | assert_equals(table.calculate_forwarding_table_row_seed(0x0000).encode('hex'), '491c53a72df4c837') 28 | assert_equals(table.calculate_forwarding_table_row_seed(0xffff).encode('hex'), 'f223c0cc65161620') 29 | 30 | def test_order_hosts_0000(self): 31 | """ 32 | GLBRendezvousTable correctly orders hosts (index=0x0000) 33 | row seed: 491c53a72df4c837 34 | 1.1.1.1 e47127dd8fe077de 35 | 1.1.1.2 8b1ddec5575c8634 36 | 1.1.1.3 705425e3e522989b 37 | 1.1.1.4 6f022ce1ea607e16 38 | """ 39 | 40 | forwarding_table_seed = '49a3d861d661ae5ab06ed9326871a2f5'.decode('hex') 41 | table = GLBRendezvousTable(forwarding_table_seed) 42 | 43 | hosts = ['1.1.1.1', '1.1.1.2', '1.1.1.3', '1.1.1.4'] 44 | a,b,c,d = hosts 45 | assert_equals(table.forwarding_table_entry(0x0000, hosts), [d,c,b,a]) 46 | 47 | def test_order_hosts_ffff(self): 48 | """ 49 | GLBRendezvousTable correctly orders hosts (index=0xffff) 50 | row seed: f223c0cc65161620 51 | 1.1.1.1 0233ef12d7a983d9 52 | 1.1.1.2 6414aa65f0a10601 53 | 1.1.1.3 af48ea8c83867829 54 | 1.1.1.4 a1f610df9fbb2025 55 | """ 56 | 57 | forwarding_table_seed = '49a3d861d661ae5ab06ed9326871a2f5'.decode('hex') 58 | table = GLBRendezvousTable(forwarding_table_seed) 59 | 60 | hosts = ['1.1.1.1', '1.1.1.2', '1.1.1.3', '1.1.1.4'] 61 | a,b,c,d = hosts 62 | assert_equals(table.forwarding_table_entry(0xffff, hosts), [a,b,d,c]) 63 | 64 | def test_order_hosts_bb44(self): 65 | """ 66 | GLBRendezvousTable correctly orders hosts (index=0xbb44) 67 | row seed: e290f8f430eb33d3 68 | 1.1.1.1 3595c936c995ae63 69 | 1.1.1.2 db40d5031678c90a 70 | 1.1.1.3 eb798632d691530c 71 | 1.1.1.4 0676eaf9cb7d2f85 72 | """ 73 | 74 | forwarding_table_seed = '49a3d861d661ae5ab06ed9326871a2f5'.decode('hex') 75 | table = GLBRendezvousTable(forwarding_table_seed) 76 | 77 | hosts = ['1.1.1.1', '1.1.1.2', '1.1.1.3', '1.1.1.4'] 78 | a,b,c,d = hosts 79 | assert_equals(table.forwarding_table_entry(0xbb44, hosts), [d,a,b,c]) 80 | -------------------------------------------------------------------------------- /src/glb-director/tests/valgrind_check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # BSD 3-Clause License 4 | # 5 | # Copyright (c) 2018 GitHub. 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # * Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from 20 | # this software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | set -e 34 | 35 | . "$BASEDIR/tests/lib/testlib.sh" 36 | 37 | valgrind --leak-check=full $BASEDIR/cli/glb-director-pcap \ 38 | --config-file $BASEDIR/tests/data/config.json \ 39 | --forwarding-table $BASEDIR/tests/data/test-tables.bin \ 40 | --packet-file $BASEDIR/tests/data/dummy1.bin &> $BASEDIR/build/cmd.out || true 41 | 42 | begin_test "make sure there are no leaks in packet file mode" 43 | ( 44 | grep -q "ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)" $BASEDIR/build/cmd.out 45 | ) 46 | end_test 47 | -------------------------------------------------------------------------------- /src/glb-director/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * Copyright (c) 2016 Intel Corporation. (original DPDK example code) 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * * Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | 37 | #ifdef RTE_EXEC_ENV_BSDAPP 38 | 39 | #ifdef __BSD_VISIBLE 40 | #include "strlcpy.h" 41 | #endif 42 | 43 | #else 44 | 45 | #ifdef RTE_USE_LIBBSD 46 | #include "strlcpy.h" 47 | #endif 48 | 49 | #endif 50 | 51 | 52 | static inline void burst_free_mbufs(struct rte_mbuf **pkts, unsigned num) 53 | { 54 | unsigned i; 55 | 56 | if (pkts == NULL) 57 | return; 58 | 59 | for (i = 0; i < num; i++) { 60 | rte_pktmbuf_free(pkts[i]); 61 | pkts[i] = NULL; 62 | } 63 | } 64 | 65 | static inline void burst_free_missed_mbufs(struct rte_mbuf **pkts, 66 | unsigned total, unsigned sent) 67 | { 68 | if (unlikely(sent < total)) { 69 | burst_free_mbufs(&pkts[sent], total - sent); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/glb-hashing/glb_gue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | #ifndef _GLB_GUE_H_ 34 | #define _GLB_GUE_H_ 35 | 36 | #define GLB_GUE_PORT 19523 /* 'LB' + 1 */ 37 | 38 | struct glb_gue_hdr { 39 | uint8_t version_control_hlen; 40 | uint8_t protocol; 41 | uint16_t flags; 42 | 43 | // GUE private data. 44 | // we only support holding GLB GUE chained routing 45 | uint16_t private_type; // will be 0 46 | uint8_t next_hop; 47 | uint8_t hop_count; 48 | 49 | uint32_t hops[]; 50 | } __attribute__((__packed__)); 51 | 52 | #endif /* _GLB_GUE_H_ */ 53 | -------------------------------------------------------------------------------- /src/glb-healthcheck/.gitignore: -------------------------------------------------------------------------------- 1 | glb-healthcheck 2 | .gopath 3 | .test 4 | vendor 5 | *.deb 6 | -------------------------------------------------------------------------------- /src/glb-healthcheck/HealthChecker.go: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package main 34 | 35 | import ( 36 | "time" 37 | ) 38 | 39 | type HealthCheckTarget struct { 40 | CheckType string 41 | Ip string 42 | Port int 43 | Uri string 44 | } 45 | 46 | type HealthResult struct { 47 | Healthy bool 48 | Failure string 49 | } 50 | 51 | type HealthResultStream chan HealthResult 52 | 53 | type HealthChecker interface { 54 | Initialize(checkTimeout time.Duration) error 55 | CheckTarget(resultChannel HealthResultStream, target HealthCheckTarget) 56 | } 57 | -------------------------------------------------------------------------------- /src/glb-healthcheck/HealthResultDampener.go: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package main 34 | 35 | import ( 36 | "expvar" 37 | ) 38 | 39 | var ( 40 | dampenerCounters = expvar.NewMap("DampenedResultStream") 41 | ) 42 | 43 | // takes a HealthResultStream and returns a similar one, except that flapping is dampened. 44 | // essentially at any given point, it takes a certain number of the same HC result before we accept 45 | // that it's accurate and start reporting it - until then we report the old value. 46 | // the values can be different for healthy/failed transitions to allow fast failure or fast return. 47 | // assumes the first result is accurate and immediately starts returning it. 48 | // the goroutine here will run until the source stream is closed, at which point it closes downstream too. 49 | func DampenedResultStream(src HealthResultStream, countBeforeHealthy int, countBeforeFailed int) HealthResultStream { 50 | dampened := make(HealthResultStream) 51 | 52 | go func() { 53 | dampenerCounters.Add("StartedStreams", 1) 54 | dampenerCounters.Add("ActiveStreams", 1) 55 | 56 | // accept the first health state as accurate 57 | reportedHealth := <-src 58 | dampened <- reportedHealth 59 | 60 | currentHealth := reportedHealth 61 | currentHealthCount := 1 62 | 63 | for nextHealth := range src { 64 | if nextHealth.Healthy == currentHealth.Healthy { 65 | // if the new value matches the last one, we've seen one more of the same 66 | currentHealthCount++ 67 | dampenerCounters.Add("HealthUnchanged", 1) 68 | } else { 69 | // otherwise, we've changed health state, so reset our count to 1 70 | currentHealthCount = 1 71 | currentHealth = nextHealth 72 | dampenerCounters.Add("HealthChangedWaitStart", 1) 73 | } 74 | 75 | // once we've seen the required count (or more) of a new value, start reporting it 76 | if currentHealth.Healthy && !reportedHealth.Healthy && currentHealthCount >= countBeforeHealthy { 77 | reportedHealth = currentHealth 78 | dampenerCounters.Add("HealthChangedHealthy", 1) 79 | } else if !currentHealth.Healthy && reportedHealth.Healthy && currentHealthCount >= countBeforeFailed { 80 | reportedHealth = currentHealth 81 | dampenerCounters.Add("HealthChangedUnhealthy", 1) 82 | } 83 | 84 | // and finally, keep sending out dampened state 85 | dampened <- reportedHealth 86 | } 87 | 88 | // pass on the closure of our source channel to the dampened one 89 | close(dampened) 90 | dampenerCounters.Add("CompletedStreams", 1) 91 | dampenerCounters.Add("ActiveStreams", -1) 92 | }() 93 | 94 | return dampened 95 | } 96 | -------------------------------------------------------------------------------- /src/glb-healthcheck/HealthResultDampener_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package main 34 | 35 | import "testing" 36 | 37 | func performDampenedTest(t *testing.T, countBeforeHealthy int, countBeforeFailed int, src []bool, expected []bool) { 38 | dummy := make(HealthResultStream) 39 | go func() { 40 | for _, v := range src { 41 | dummy <- HealthResult{Healthy: v} 42 | } 43 | close(dummy) 44 | }() 45 | 46 | dampened := DampenedResultStream(dummy, countBeforeHealthy, countBeforeFailed) 47 | for i, exp := range expected { 48 | actual := <-dampened 49 | if actual.Healthy != exp { 50 | t.Errorf("Expected %v at index %d, got %v", exp, i, actual) 51 | } 52 | } 53 | } 54 | 55 | func TestDampenedResultStreamNoDampening(t *testing.T) { 56 | src_stream := []bool{true, false, true, false, true, false} 57 | out_stream := []bool{true, false, true, false, true, false} 58 | 59 | performDampenedTest(t, 1, 1, src_stream, out_stream) 60 | } 61 | 62 | func TestDampenedResultStreamImmediateHealthySlowFailure(t *testing.T) { 63 | src_stream := []bool{false, false, true, false, true, false, false, false, false, false, true, false} 64 | out_stream := []bool{false, false, true, true, true, true, true, false, false, false, true, true} 65 | 66 | performDampenedTest(t, 1, 3, src_stream, out_stream) 67 | } 68 | 69 | func TestDampenedResultStreamImmediateFailureSlowHealth(t *testing.T) { 70 | src_stream := []bool{true, true, false, true, false, true, true, true, true, true, false, true} 71 | out_stream := []bool{true, true, false, false, false, false, false, true, true, true, false, false} 72 | 73 | performDampenedTest(t, 3, 1, src_stream, out_stream) 74 | } 75 | 76 | func TestDampenedResultStreamSlowFailureSlowHealth(t *testing.T) { 77 | src_stream := []bool{false, false, true, false, true, false, false, false, false, false, true, false, true, true, true, true, true} 78 | out_stream := []bool{false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true} 79 | 80 | performDampenedTest(t, 3, 3, src_stream, out_stream) 81 | 82 | src_stream = []bool{true, true, false, true, false, true, true, true, true, true, false, true, false, false, false, false, false} 83 | out_stream = []bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false} 84 | 85 | performDampenedTest(t, 3, 3, src_stream, out_stream) 86 | } 87 | -------------------------------------------------------------------------------- /src/glb-healthcheck/HttpHealthChecker.go: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, this 11 | * list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the copyright holder nor the names of its 18 | * contributors may be used to endorse or promote products derived from 19 | * this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package main 34 | 35 | import ( 36 | "expvar" 37 | "fmt" 38 | log "github.com/sirupsen/logrus" 39 | "net/http" 40 | "time" 41 | ) 42 | 43 | var ( 44 | httpCounters = expvar.NewMap("HttpHealthChecker") 45 | ) 46 | 47 | type HttpHealthChecker struct { 48 | checkTimeout time.Duration 49 | } 50 | 51 | // runs an HTTP GET on a given URL and returns a one-shot result stream 52 | // that will be given a HealthResult once completed 53 | func httpCheckURL(url string, timeoutSec time.Duration) HealthResultStream { 54 | ch := make(HealthResultStream, 1) 55 | 56 | go func() { 57 | httpCounters.Add("Checks", 1) 58 | var httpClient = &http.Client { 59 | Timeout: timeoutSec, 60 | } 61 | resp, err := httpClient.Get(url) 62 | if err != nil { 63 | ch <- HealthResult{Healthy: false, Failure: err.Error()} 64 | close(ch) 65 | httpCounters.Add("CheckFailedError", 1) 66 | return 67 | } 68 | 69 | resp.Body.Close() 70 | if resp.StatusCode == 200 { 71 | ch <- HealthResult{Healthy: true, Failure: ""} 72 | httpCounters.Add("CheckOk", 1) 73 | } else { 74 | ch <- HealthResult{Healthy: false, Failure: fmt.Sprintf("HTTP server responded with %d, expecting 200.", resp.StatusCode)} 75 | httpCounters.Add("CheckFailedStatus", 1) 76 | } 77 | close(ch) 78 | }() 79 | 80 | return ch 81 | } 82 | 83 | func (h *HttpHealthChecker) Initialize(checkTimeout time.Duration) error { 84 | h.checkTimeout = checkTimeout 85 | 86 | return nil 87 | } 88 | 89 | func (h *HttpHealthChecker) CheckTarget(resultChannel HealthResultStream, target HealthCheckTarget) { 90 | logContext := log.WithFields(log.Fields{ 91 | "checker": "http", 92 | "checkType": target.CheckType, 93 | "targetIp": target.Ip, 94 | "targetPort": target.Port, 95 | }) 96 | 97 | go func() { 98 | logContext.Debug("Sending HTTP request to health check port") 99 | resultCh := httpCheckURL(fmt.Sprintf("http://%s:%d%s", target.Ip, target.Port, target.Uri), h.checkTimeout) 100 | 101 | // either receive the successful result, or time out and craft an error result. 102 | var result HealthResult 103 | select { 104 | case r := <-resultCh: 105 | result = r 106 | case <-time.After(h.checkTimeout): 107 | result = HealthResult{Healthy: false, Failure: fmt.Sprintf("No response received within HTTP check timeout of %d", h.checkTimeout)} 108 | httpCounters.Add("CheckTimeout", 1) 109 | } 110 | 111 | logContext.WithFields(log.Fields{ 112 | "healthy": result.Healthy, 113 | "healthFailure": result.Failure, 114 | }).Debug("HTTP health check result completed") 115 | 116 | // pass on the result directly to the caller's channel 117 | resultChannel <- result 118 | }() 119 | } 120 | -------------------------------------------------------------------------------- /src/glb-healthcheck/Makefile: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License 2 | # 3 | # Copyright (c) 2018 GitHub. 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 | # * Redistributions of source code must retain the above copyright notice, this 10 | # list of conditions and the following disclaimer. 11 | # 12 | # * 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 | # * 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 | 31 | mkdeb: 32 | script/cibuild 33 | 34 | clean: 35 | rm -rf glb-healthcheck_*.deb glb-healthcheck 36 | -------------------------------------------------------------------------------- /src/glb-healthcheck/README.md: -------------------------------------------------------------------------------- 1 | # glb-healthcheck 2 | 3 | This module takes a forwarding table JSON file for `glb-director` and runs healthchecks on the backend nodes included within, and outputs a new forwarding table where the health state of backends is included. 4 | 5 | ## License 6 | 7 | The `glb-healthcheck` component contained within this directory is licensed under the [BSD 3-Clause License](../../LICENSE.md). 8 | -------------------------------------------------------------------------------- /src/glb-healthcheck/TcpHealthChecker.go: -------------------------------------------------------------------------------- 1 | /* 2 | * BSD 3-Clause License 3 | * 4 | * Copyright (c) 2019 Roblox Corporation. 5 | * Copyright (c) 2018 GitHub. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 11 | * * Redistributions of source code must retain the above copyright notice, this 12 | * list of conditions and the following disclaimer. 13 | * 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * 18 | * * Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | package main 35 | 36 | import ( 37 | "expvar" 38 | "fmt" 39 | log "github.com/sirupsen/logrus" 40 | "net" 41 | "time" 42 | ) 43 | 44 | var ( 45 | tcpCounters = expvar.NewMap("TcpHealthChecker") 46 | ) 47 | 48 | type TcpHealthChecker struct { 49 | checkTimeout time.Duration 50 | } 51 | 52 | func OpenConnection(resultChannel HealthResultStream, ip_port string) HealthResultStream { 53 | ch := make(HealthResultStream, 1) 54 | 55 | go func() { 56 | c, err := net.Dial("tcp", ip_port) 57 | if err != nil { 58 | ch <- HealthResult{Healthy: false, Failure: err.Error()} 59 | tcpCounters.Add("CheckFailedStatus", 1) 60 | } else { 61 | ch <- HealthResult{Healthy: true, Failure: ""} 62 | tcpCounters.Add("CheckOK", 1) 63 | c.Close() 64 | } 65 | close(ch) 66 | }() 67 | 68 | return ch 69 | } 70 | 71 | // 72 | // Attempt to open a TCP connection to the specified ip:port. 73 | // If the connection can be opened, the remote endpoint is considered healthy 74 | // 75 | func (t *TcpHealthChecker) Initialize(checkTimeout time.Duration) error { 76 | t.checkTimeout = checkTimeout 77 | 78 | return nil 79 | } 80 | 81 | func (t *TcpHealthChecker) CheckTarget(resultChannel HealthResultStream, 82 | target HealthCheckTarget) { 83 | logContext := log.WithFields(log.Fields{ 84 | "checker": "tcp", 85 | "checkType": target.CheckType, 86 | "targetIp": target.Ip, 87 | "targetPort": target.Port, 88 | }) 89 | 90 | go func() { 91 | logContext.Debug("Sending TCP connection request") 92 | resultCh := OpenConnection(resultChannel, fmt.Sprintf("%s:%d", target.Ip, target.Port)) 93 | 94 | var result HealthResult 95 | select { 96 | case r := <-resultCh: 97 | result = r 98 | case <-time.After(t.checkTimeout): 99 | result = HealthResult{Healthy: false, Failure: fmt.Sprintf("No response received within TCP check timeout of %d", t.checkTimeout)} 100 | tcpCounters.Add("CheckTimeout", 1) 101 | } 102 | 103 | logContext.WithFields(log.Fields{ 104 | "healthy": result.Healthy, 105 | "healthFailure": result.Failure, 106 | }).Debug("TCP health check result completed") 107 | 108 | // pass on the result directly to the caller's channel 109 | resultChannel <- result 110 | }() 111 | } 112 | -------------------------------------------------------------------------------- /src/glb-healthcheck/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/github/glb-director/src/glb-healthcheck 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/docopt/docopt-go v0.0.0-20160216232012-784ddc588536 7 | github.com/google/gopacket v1.1.14 8 | github.com/onsi/ginkgo v1.16.5 // indirect 9 | github.com/onsi/gomega v1.27.8 // indirect 10 | github.com/rs/xid v0.0.0-20170604230408-02dd45c33376 11 | github.com/sirupsen/logrus v1.0.5 12 | github.com/stretchr/testify v1.8.4 // indirect 13 | golang.org/x/crypto v0.35.0 // indirect 14 | gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect 15 | gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /src/glb-healthcheck/packaging/forwarding_table.checked.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /src/glb-healthcheck/packaging/forwarding_table.src.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /src/glb-healthcheck/packaging/glb-healthcheck.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=GLB Director Healthcheck 3 | After=network.target network-online.target 4 | Wants=network-online.target 5 | 6 | [Service] 7 | Type=simple 8 | Restart=always 9 | ExecStart=/usr/sbin/glb-healthcheck --config=/etc/glb/healthcheck.conf 10 | ExecReload=/bin/kill -HUP $MAINPID 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /src/glb-healthcheck/packaging/healthcheck.conf: -------------------------------------------------------------------------------- 1 | { 2 | "forwarding_table": { 3 | "src": "/etc/glb/forwarding_table.src.json", 4 | "dst": "/etc/glb/forwarding_table.checked.json" 5 | }, 6 | "reload_command": "glb-director-cli build-config /etc/glb/forwarding_table.checked.json /etc/glb/forwarding_table.checked.bin && systemctl reload glb-director" 7 | } 8 | -------------------------------------------------------------------------------- /src/glb-healthcheck/packaging/version.sh: -------------------------------------------------------------------------------- 1 | GLB_HEALTHCHECK_VERSION="0.1.8" 2 | -------------------------------------------------------------------------------- /src/glb-healthcheck/script/cibuild: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # BSD 3-Clause License 4 | # 5 | # Copyright (c) 2018 GitHub. 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # * Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from 20 | # this software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | set -e 34 | ROOTDIR=$(dirname $0)/.. 35 | cd $ROOTDIR 36 | 37 | . packaging/version.sh 38 | 39 | go build -buildvcs=false 40 | 41 | fpm -f -s dir -t deb \ 42 | -n glb-healthcheck \ 43 | -v ${GLB_HEALTHCHECK_VERSION} \ 44 | --license 'BSD 3-Clause' \ 45 | --maintainer 'GitHub ' \ 46 | --deb-systemd packaging/glb-healthcheck.service \ 47 | --config-files /etc/glb \ 48 | glb-healthcheck=/usr/sbin/ \ 49 | packaging/healthcheck.conf=/etc/glb/ \ 50 | packaging/forwarding_table.src.json=/etc/glb/ \ 51 | packaging/forwarding_table.checked.json=/etc/glb/ 52 | 53 | if [ -d "$BUILDDIR" ]; then 54 | cp glb-healthcheck_${GLB_HEALTHCHECK_VERSION}_amd64.deb $BUILDDIR/ 55 | fi 56 | -------------------------------------------------------------------------------- /src/glb-healthcheck/script/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # 3 | # BSD 3-Clause License 4 | # 5 | # Copyright (c) 2018 GitHub. 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # * Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from 20 | # this software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 26 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | set -e 34 | ROOTDIR=$(dirname $0)/.. 35 | cd $ROOTDIR 36 | 37 | echo 'Building...' 38 | go build 39 | 40 | date "+%Y-%m-%dT%H:%M:%SZ" 41 | echo "Beginning tests" 42 | echo "=== GO TEST ===" 43 | 44 | go test -v 45 | 46 | echo "=== SHELL TEST ===" 47 | 48 | ls -1 test/test-*.sh | xargs -I % -n 1 /bin/bash % 49 | 50 | echo "===" 51 | date "+%Y-%m-%dT%H:%M:%SZ" 52 | echo "Done." 53 | -------------------------------------------------------------------------------- /src/glb-redirect/Makefile: -------------------------------------------------------------------------------- 1 | KDIR?=/usr/src/linux-headers-$(shell uname -r) 2 | BUILDDIR?=. 3 | 4 | ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 5 | 6 | DKMS_MOD_VER:=$(shell grep 'PACKAGE_VERSION' dkms.conf | cut -d'=' -f2) 7 | 8 | obj-m += ipt_GLBREDIRECT.o 9 | 10 | all: lib kmod 11 | 12 | kmod: 13 | $(BUILD_VARS) make -C $(KDIR) M=$(ROOT_DIR) modules 14 | 15 | clean: 16 | # we allow the following to fail since in our Docker build env we don't have a valid KDIR 17 | $(BUILD_VARS) make -C $(KDIR) M=$(ROOT_DIR) clean || true 18 | rm -rf libxt_GLBREDIRECT.so $(BUILDDIR)/glb-redirect-iptables-dkms_$(DKMS_MOD_VER)_*.deb 19 | 20 | .PHONY: lib 21 | lib: libxt_GLBREDIRECT.so 22 | 23 | .PHONY: install 24 | install: lib kmod 25 | install -d $(DESTDIR)$(shell pkg-config --variable=xtlibdir xtables) 26 | install -m 0755 libxt_GLBREDIRECT.so $(DESTDIR)$(shell pkg-config --variable=xtlibdir xtables) 27 | install -d $(DESTDIR)/lib/modules/$(shell uname -r)/updates 28 | install ipt_GLBREDIRECT.ko $(DESTDIR)/lib/modules/$(shell uname -r)/updates 29 | 30 | KSRC=/usr/src/linux-headers-$(shell uname -r) 31 | IPT_CFLAGS=-DPIC -fPIC -Wno-cpp 32 | IPT_LDFLAGS=-lxtables -shared 33 | 34 | %.so: %.c 35 | $(CC) -o $@ $< $(IPT_CFLAGS) $(IPT_LDFLAGS) 36 | 37 | mkdeb: 38 | rm -rf glb-redirect-iptables-dkms-mkdeb 39 | cp -R /etc/dkms/template-dkms-mkdeb/ glb-redirect-iptables-dkms-mkdeb 40 | chown : -R glb-redirect-iptables-dkms-mkdeb 41 | # Works around this bug: https://ubuntuforums.org/showthread.php?t=2234906 42 | sed -i '/chmod 644/d' glb-redirect-iptables-dkms-mkdeb/Makefile 43 | sed -i '/^Depends:/ s/$$/, pkg-config, libxtables12 | libxtables10, libxtables-dev | libxtables10/' glb-redirect-iptables-dkms-mkdeb/debian/control 44 | sed -i 's/^Maintainer: .*/Maintainer: GitHub /' glb-redirect-iptables-dkms-mkdeb/debian/control 45 | dkms mkdeb --source-only 46 | mv ../glb-redirect-iptables-dkms_$(DKMS_MOD_VER)_*.deb $(BUILDDIR)/ 47 | -------------------------------------------------------------------------------- /src/glb-redirect/README.md: -------------------------------------------------------------------------------- 1 | # glb-redirect iptables module 2 | 3 | This module provides the "second chance" packet processing function of GLB by processing inbound [GLB GUE](../../docs/development/gue-header.md) packets before the Linux networking stack processes and decapsulates them, and forwarding packets that would not be valid TCP packets on the local machine (because they are for a non-local connection) to an alternate server. 4 | 5 | ## License 6 | 7 | The `glb-redirect` component contained within this directory is licensed under the [GPL V2](../../LICENSE.md) to make it license compatible with the Linux Kernel. 8 | -------------------------------------------------------------------------------- /src/glb-redirect/dkms.conf: -------------------------------------------------------------------------------- 1 | MAKE="make KDIR=/lib/modules/${kernelver}/build" 2 | CLEAN="make clean" 3 | PACKAGE_NAME=glb-redirect-iptables 4 | PACKAGE_VERSION=1.0.6 5 | REMAKE_INITRD=no 6 | 7 | BUILT_MODULE_NAME=ipt_GLBREDIRECT 8 | DEST_MODULE_LOCATION="/updates" 9 | 10 | POST_INSTALL="install-ipt.sh" 11 | 12 | AUTOINSTALL="yes" 13 | -------------------------------------------------------------------------------- /src/glb-redirect/install-ipt.sh: -------------------------------------------------------------------------------- 1 | make clean lib 2 | install -d $(pkg-config --variable=xtlibdir xtables) 3 | install -m 0755 libxt_GLBREDIRECT.so $(pkg-config --variable=xtlibdir xtables) 4 | -------------------------------------------------------------------------------- /src/glb-redirect/ipt_glbredirect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libxt_GLBREDIRECT: iptables target for GLB proxy alternate fallback 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * 6 | * This file is part of the `glb-redirect` iptables module. 7 | * 8 | * glb-redirect is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * glb-redirect is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with glb-redirect. If not, see . 20 | */ 21 | 22 | #ifndef __IPT_GLBREDIRECT_MATCH__ 23 | #define __IPT_GLBREDIRECT_MATCH__ 24 | 25 | struct ipt_glbredirect_info { 26 | 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/glb-redirect/libxt_GLBREDIRECT.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libxt_GLBREDIRECT: iptables target for GLB proxy alternate fallback 3 | * 4 | * Copyright (c) 2018 GitHub. 5 | * 6 | * This file is part of the `glb-redirect` iptables module. 7 | * 8 | * glb-redirect is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * glb-redirect is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with glb-redirect. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include "ipt_glbredirect.h" 27 | 28 | static void GLBREDIRECT_help(void) 29 | { 30 | printf( 31 | "GLBREDIRECT target options:\n" 32 | " none\n"); 33 | } 34 | 35 | static const struct xt_option_entry GLBREDIRECT_opts[] = { 36 | XTOPT_TABLEEND, 37 | }; 38 | 39 | static void GLBREDIRECT_parse(struct xt_option_call *cb) 40 | { 41 | xtables_option_parse(cb); 42 | } 43 | 44 | static void GLBREDIRECT_check(struct xt_fcheck_call *cb) 45 | { 46 | } 47 | 48 | static void GLBREDIRECT_print(const void *ip, const struct xt_entry_target *target, 49 | int numeric) 50 | { 51 | const struct ipt_proxyalt_info *info = 52 | (const struct ipt_proxyalt_info *)target->data; 53 | 54 | printf(" GLBREDIRECT "); 55 | } 56 | 57 | static void GLBREDIRECT_save(const void *ip, const struct xt_entry_target *target) 58 | { 59 | 60 | } 61 | 62 | static struct xtables_target glbredirect_tg_reg = { 63 | .family = NFPROTO_UNSPEC, 64 | .name = "GLBREDIRECT", 65 | .version = XTABLES_VERSION, 66 | .revision = 0, 67 | .size = XT_ALIGN(sizeof(struct ipt_glbredirect_info)), 68 | .userspacesize = XT_ALIGN(sizeof(struct ipt_glbredirect_info)), 69 | .help = GLBREDIRECT_help, 70 | .print = GLBREDIRECT_print, 71 | .save = GLBREDIRECT_save, 72 | .x6_parse = GLBREDIRECT_parse, 73 | .x6_fcheck = GLBREDIRECT_check, 74 | .x6_options = GLBREDIRECT_opts, 75 | }; 76 | 77 | void _init(void) 78 | { 79 | xtables_register_target(&glbredirect_tg_reg); 80 | } 81 | -------------------------------------------------------------------------------- /src/glb-redirect/script/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (c) 2018 GitHub. 4 | # 5 | # This file is part of the `glb-redirect` test suite. 6 | # 7 | # This file is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This file is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this project. If not, see . 19 | 20 | set -e 21 | 22 | HOSTPATH=$(cd $(dirname "$0") && cd .. && pwd) 23 | cd "$(dirname "$0")/.." 24 | 25 | PYTHONPATH=$(pwd)/../scapy-glb-gue/:$PYTHONPATH nosetests -v 26 | -------------------------------------------------------------------------------- /src/glb-redirect/tests/glb_test_remote_snoop.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 GitHub. 2 | # 3 | # This file is part of the `glb-redirect` test suite. 4 | # 5 | # This file is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This file is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this project. If not, see . 17 | 18 | from scapy.data import ETH_P_IP, ETH_P_IPV6 19 | from scapy.all import Ether 20 | import socket, time, struct 21 | 22 | class RemoteSnoop(object): 23 | def __init__(self, remote_host, remote_port=9999, remote_type=ETH_P_IP, remote_iface='tunl0', debug=False): 24 | self.debug = debug 25 | self.remote_host = remote_host 26 | # connect now so we start receiving our packets 27 | self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 28 | self.s.connect((remote_host, remote_port)) 29 | 30 | # send the ethertype and interface we expect 31 | # (2 byte ethertype, 4 byte iface len, ) 32 | raw_iface = remote_iface.encode('ascii') 33 | self.s.sendall(struct.pack('!HI', remote_type, len(raw_iface))) 34 | self.s.sendall(raw_iface) 35 | 36 | # receive some bytes, so we know we're in sync and listening on the remote end 37 | assert self.s.recv(4) == 'SYNC' 38 | 39 | def recv(self, recv_filter, timeout=10): 40 | self.s.settimeout(timeout) 41 | start = time.time() 42 | while time.time() < start + timeout: 43 | pkt_len_raw = self.s.recv(4) 44 | pkt_len, = struct.unpack('!I', pkt_len_raw) 45 | pkt_raw = self.s.recv(pkt_len) 46 | 47 | # we don't actually want Ether header, it's just a stub so we know the protocol. 48 | # this means we can be lazy and Scapy do all the encoding/decoding work. 49 | pkt_ether = Ether(pkt_raw) 50 | pkt = pkt_ether.payload 51 | 52 | if self.debug: print("got packet from {}: {}".format(self.remote_host, repr(pkt))) 53 | if recv_filter(pkt): 54 | if self.debug: print(" -> match!") 55 | return pkt 56 | else: 57 | if self.debug: print(" -> not a match.") 58 | return None 59 | -------------------------------------------------------------------------------- /src/glb-redirect/tests/glb_test_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 GitHub. 2 | # 3 | # This file is part of the `glb-redirect` test suite. 4 | # 5 | # This file is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This file is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this project. If not, see . 17 | 18 | from scapy.all import sniff, send, L3RawSocket, L3RawSocket6 19 | 20 | class GLBTestHelpers(object): 21 | def _sendrecv6(self, pkt, **kwargs): 22 | s = L3RawSocket6() 23 | send(pkt) 24 | ret = sniff(opened_socket=s, timeout=1, **kwargs) 25 | s.close() 26 | if len(ret) == 0: 27 | assert False, "Expected to receive a response packet, but none received." 28 | print "Received packet:", repr(ret[0]) 29 | return ret[0] 30 | 31 | def _sendrecvmany4(self, pkt, **kwargs): 32 | s = L3RawSocket() 33 | s.send(pkt) 34 | ret = s.sniff(timeout=1, **kwargs) 35 | s.close() 36 | if len(ret) == 0: 37 | assert False, "Expected to receive a response packet, but none received." 38 | for pkt in ret: 39 | print "Received packet:", repr(pkt) 40 | return ret 41 | 42 | def _sendrecv4(self, pkt, **kwargs): 43 | return self._sendrecvmany4(pkt, count=1, **kwargs)[0] 44 | 45 | @staticmethod 46 | def _match_tuple(saddr, daddr, sport, dport): 47 | return lambda p: p.src == saddr and p.dst == daddr and p.payload.sport == sport and p.payload.dport == dport 48 | -------------------------------------------------------------------------------- /src/glb-wireshark-dissector/README.md: -------------------------------------------------------------------------------- 1 | # glb-wireshark-dissector 2 | 3 | This GLB/GUE dissector for Wireshark supports dissecting the [GLB extension to GUE](../../docs/development/gue-header.md). 4 | 5 | ## Installation 6 | 7 | Put the contents of this directory under `~/.config/wireshark/plugins/glb-wireshark-dissector` and Wireshark should automatically load the plugin on startup. 8 | 9 | ## License 10 | 11 | The `glb-wireshark-dissector` component contained within this directory is licensed under the [GPL V2](../../LICENSE.md) to make it license compatible with the Wireshark. 12 | -------------------------------------------------------------------------------- /src/scapy-glb-gue/README.md: -------------------------------------------------------------------------------- 1 | # scapy-glb-gue scapy GLB/GUE extension 2 | 3 | This module allows Scapy to decode [GLB GUE headers](../../docs/development/gue-header.md). 4 | 5 | ## License 6 | 7 | The `scapy-glb-gue` component contained within this directory is licensed under the [GPL V2](../../LICENSE.md) to make it license compatible with Scapy. 8 | -------------------------------------------------------------------------------- /src/scapy-glb-gue/glb_scapy/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018 GitHub. 2 | # 3 | # This file is part of the `scapy-glb-gue` scapy extension. 4 | # 5 | # scapy-glb-gue is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # scapy-glb-gue is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with scapy-glb-gue. If not, see . 17 | 18 | from glb_gue_scapy import GLBGUEChainedRouting, GLBGUE 19 | -------------------------------------------------------------------------------- /src/scapy-glb-gue/glb_scapy/glb_gue_scapy.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # 3 | # Copyright (c) 2018 GitHub. 4 | # 5 | # This file is part of the `scapy-glb-gue` scapy extension. 6 | # 7 | # scapy-glb-gue is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # scapy-glb-gue is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with scapy-glb-gue. If not, see . 19 | 20 | # Set log level to benefit from Scapy warnings 21 | import logging 22 | logging.getLogger("scapy").setLevel(1) 23 | 24 | from scapy.all import * 25 | 26 | class GLBGUEChainedRouting(Packet): 27 | name = "GLBGUEChainedRouting" 28 | fields_desc = [ 29 | ShortField('private_type', 0), 30 | ByteField("next_hop", 0), 31 | FieldLenField("hop_count", None, count_of='hops', fmt='B'), 32 | FieldListField("hops", [], IPField("", "0.0.0.0"), count_from=lambda pkt: pkt.hop_count), 33 | ] 34 | 35 | class GLBGUE(Packet): 36 | name = "GLBGUE" 37 | fields_desc = [BitField("version", 0, 2), 38 | BitField("control_msg", 0, 1), 39 | BitFieldLenField("hlen", None, 5, length_of='private_data', adjust=lambda pkt, x: (x / 4)), 40 | BitField("protocol", 0, 8), 41 | BitField("flags", 0, 16), 42 | PacketListField("private_data", [], GLBGUEChainedRouting, length_from=lambda p:p.hlen * 4) 43 | ] 44 | 45 | bind_layers(UDP, GLBGUE, dport=19523) 46 | bind_layers(GLBGUE, IP, protocol=4) 47 | bind_layers(GLBGUE, IPv6, protocol=41) 48 | 49 | 50 | # print repr(IP(str(IP(dst='192.168.50.10')/UDP(sport=12345, dport=19523)/GLBGUE(private_data=GLBGUEChainedRouting(hops=['8.7.6.5', '1.2.3.4']))/IP(src='192.168.50.123', dst='192.168.50.10')/TCP(sport=123, dport=456)))) 51 | 52 | if __name__ == "__main__": 53 | interact(mydict=globals(), mybanner="GLB GUE add-on") 54 | --------------------------------------------------------------------------------