├── .gitignore
├── logo.png
├── tools
├── CMakeLists.txt
├── wireshark
│ ├── README.md
│ └── guev1.lua
├── README.md
├── xdpdump
│ ├── CMakeLists.txt
│ ├── XdpEventReader.cpp
│ ├── XdpDumpStructs.h
│ ├── XdpEventLogger.cpp
│ ├── XdpEventReader.h
│ └── XdpEventLogger.h
├── start_katran
│ ├── build_start_katran.sh
│ └── start_katran
│ │ └── src
│ │ └── start_katran
│ │ ├── katranc
│ │ └── katranc.go
│ │ ├── topology_parser
│ │ └── topology_parser.go
│ │ ├── start_binary
│ │ └── start_binary.go
│ │ └── default_watcher
│ │ └── default_watcher.go
└── tcpdump_encap_helper
│ └── README.md
├── imgs
├── katran_pktflow.png
└── katran_consistency.png
├── katran
├── tpr
│ ├── README
│ ├── bpf_util
│ │ ├── CMakeLists.txt
│ │ ├── BpfUtil.h
│ │ ├── BpfSkeleton.h
│ │ └── BpfUtil.cpp
│ ├── bpf
│ │ ├── tcp_pkt_router_maps.h
│ │ ├── tcp_pkt_router_structs.h
│ │ └── tcp_pkt_router_consts.h
│ ├── CMakeLists.txt
│ ├── TPRStatsPoller.h
│ └── TPRTypes.h
├── lib
│ ├── bpf
│ │ ├── balancer_kern-tpl.h
│ │ ├── balancer_kern_flavors-tpl.h
│ │ ├── xdp_root.c
│ │ ├── flow_debug.h
│ │ ├── healthchecking_structs.h
│ │ ├── flow_debug_maps.h
│ │ ├── healthchecking_consts.h
│ │ ├── xdp_pktcntr.c
│ │ ├── introspection.h
│ │ ├── healthchecking_maps.h
│ │ └── control_data_maps.h
│ ├── MonitoringStructs.cpp
│ ├── MurmurHash3.h
│ ├── MacHelpers.h
│ ├── PipeWriter.cpp
│ ├── Makefile-bpf
│ ├── ByteRangeWriter.cpp
│ ├── CHHelpers.cpp
│ ├── testing
│ │ ├── utils
│ │ │ ├── Base64Test.cpp
│ │ │ ├── Base64Helpers.h
│ │ │ ├── KatranTestUtil.h
│ │ │ └── Base64Helpers.cpp
│ │ ├── tools
│ │ │ └── PacketAttributes.h
│ │ └── CMakeLists.txt
│ ├── IOBufWriter.cpp
│ ├── tests
│ │ ├── CMakeLists.txt
│ │ ├── common
│ │ │ └── TestMain.cpp
│ │ ├── IpHelpersTest.cpp
│ │ └── PipeWriterTest.cpp
│ ├── linux_includes
│ │ ├── bpf_common.h
│ │ ├── bpf_endian.h
│ │ └── jhash.h
│ ├── FileWriter.h
│ ├── IOBufWriter.h
│ ├── PcapMsg.cpp
│ ├── ByteRangeWriter.h
│ ├── MaglevBase.cpp
│ ├── KatranEventReader.h
│ ├── PcapStructs.h
│ ├── MaglevHashV2.h
│ ├── MaglevHash.h
│ ├── FileWriter.cpp
│ ├── KatranEventReader.cpp
│ ├── MaglevBase.h
│ ├── MacHelpers.cpp
│ ├── IpHelpers.h
│ ├── MonitoringStructs.h
│ ├── PcapMsgMeta.cpp
│ ├── MurmurHash3.cpp
│ ├── MaglevHash.cpp
│ ├── IpHelpers.cpp
│ ├── CHHelpers.h
│ ├── PcapMsgMeta.h
│ ├── BpfAdapter.cpp
│ ├── MaglevHashV2.cpp
│ ├── BpfAdapter.h
│ ├── KatranSimulator.h
│ ├── DataWriter.h
│ ├── PcapMsg.h
│ ├── xdproot.cpp
│ ├── Netlink.h
│ ├── KatranSimulatorUtils.h
│ └── EventPipeCallback.cpp
├── CMakeLists.txt
└── decap
│ ├── testing
│ └── CMakeLists.txt
│ ├── CMakeLists.txt
│ ├── Makefile-bpf
│ ├── tc_bpf
│ ├── tc_decap_info_user_structs.h
│ ├── tc_decap_info_maps.h
│ ├── tc_decap_maps.h
│ └── tc_decap_stats_maps.h
│ ├── bpf
│ └── decap_maps.h
│ ├── XdpDecapStructs.h
│ └── XdpDecap.h
├── collect_debug_lb.sh
├── collect_debug_real.sh
├── os_run_tester.sh
├── .github
└── workflows
│ └── stale.yml
├── start_katran_grpc_server.sh
├── start_katran_simple_server.sh
├── CONTRIBUTING.md
├── cmake
├── katran-config.cmake.in
└── KatranTest.cmake
├── install_xdproot.sh
├── example_grpc
├── GrpcSignalHandler.h
├── GrpcSignalHandler.cpp
├── build_grpc_client.sh
└── CMakeLists.txt
└── CMakeLists.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | _build/
2 | .vscode/
3 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/facebookincubator/katran/HEAD/logo.png
--------------------------------------------------------------------------------
/tools/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required (VERSION 3.5)
2 | add_subdirectory(xdpdump)
3 |
--------------------------------------------------------------------------------
/imgs/katran_pktflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/facebookincubator/katran/HEAD/imgs/katran_pktflow.png
--------------------------------------------------------------------------------
/imgs/katran_consistency.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/facebookincubator/katran/HEAD/imgs/katran_consistency.png
--------------------------------------------------------------------------------
/katran/tpr/README:
--------------------------------------------------------------------------------
1 | TPR: TCP Packet Routing is a STATELESS solution to consistently route TCP packets where both
2 | endpoints can be controlled.
3 |
--------------------------------------------------------------------------------
/katran/lib/bpf/balancer_kern-tpl.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #pragma once
4 |
5 | namespace katran {
6 |
7 | unsigned char kBalancerKernProgBuffer[] = {__HexdumpPlaceholder__};
8 |
9 | } // namespace katran
10 |
--------------------------------------------------------------------------------
/katran/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required (VERSION 3.5)
2 | set(CMAKE_CXX_STANDARD 20)
3 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
4 | add_subdirectory(lib)
5 | add_subdirectory(decap)
6 | if(DEFINED ENV{CMAKE_BUILD_KATRAN_TPR})
7 | add_subdirectory(tpr)
8 | endif()
9 |
--------------------------------------------------------------------------------
/katran/lib/bpf/balancer_kern_flavors-tpl.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #pragma once
4 |
5 | namespace katran {
6 |
7 | unsigned char kBalancerKernProgBuffer_{flavor}[] = {__HexdumpPlaceholder__};
8 |
9 | } // namespace katran
10 |
--------------------------------------------------------------------------------
/katran/decap/testing/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(xdpdecap_tester
2 | xdpdecap_tester.cpp
3 | XdpDecapGueTestFixtures.h
4 | XdpDecapTestFixtures.h
5 | )
6 |
7 | target_link_libraries(xdpdecap_tester
8 | "${GFLAGS}"
9 | "${PTHREAD}"
10 | bpftester
11 | decap
12 | )
13 |
--------------------------------------------------------------------------------
/tools/wireshark/README.md:
--------------------------------------------------------------------------------
1 | # wireshark plugin to parse GUE variant 1 encapsulation
2 |
3 | ## installation:
4 | in your home dir create this directory:
5 | ```
6 | mkdir -p ~/.config/wireshark/plugins/guev1
7 | ```
8 |
9 | then copy guev1.lua into it. wireshark on startup automatically enables this plugin and would try to parse everything w/ UDP destination port 6080 as GUEv1 encapsulated
10 |
--------------------------------------------------------------------------------
/tools/README.md:
--------------------------------------------------------------------------------
1 | # collection of tools for katran
2 |
3 | ### xdpdump
4 | tcpdump like tool, which is working in XDP environment
5 |
6 | ### tcpdump_encap_helper
7 | helper script to create filters for tcpdump based on inner ip header
8 |
9 | ### start_katran
10 | helper tool (example of how it could looks like to be more precise)
11 | to do cpu/NUMA topology discovery, NIC's IRQ affinitization and start katran
12 | server (GRPc only in this example)
13 |
--------------------------------------------------------------------------------
/katran/tpr/bpf_util/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required (VERSION 3.9)
2 | set(KATRAN_TPR_INCLUDE_DIR "$")
3 |
4 | find_package(Glog REQUIRED)
5 | find_package(folly CONFIG REQUIRED)
6 | find_package(Threads)
7 |
8 | add_library(bpf_util STATIC
9 | BpfUtil.cpp
10 | )
11 |
12 | target_compile_definitions(bpf_util PUBLIC KATRAN_CMAKE_BUILD=1)
13 |
14 | target_link_libraries(bpf_util
15 | "Folly::folly"
16 | glog::glog
17 | ${BPF_LINK_LIBRARIES}
18 | )
19 |
20 | target_include_directories(
21 | bpf_util PUBLIC
22 | ${GFLAGS_INCLUDE_DIR}
23 | ${KATRAN_TPR_INCLUDE_DIR}
24 | )
25 |
--------------------------------------------------------------------------------
/katran/decap/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required (VERSION 3.9)
2 | set(KATRAN_INCLUDE_DIR "$")
3 |
4 | find_package(Glog REQUIRED)
5 | find_package(folly CONFIG REQUIRED)
6 | find_package(Threads)
7 |
8 | add_library(decap STATIC
9 | XdpDecap.cpp
10 | XdpDecap.h
11 | XdpDecapStructs.h
12 | )
13 |
14 | target_link_libraries(decap
15 | bpfadapter
16 | "Folly::folly"
17 | glog::glog
18 | )
19 |
20 | target_include_directories(
21 | decap PUBLIC
22 | ${GFLAGS_INCLUDE_DIR}
23 | ${KATRAN_INCLUDE_DIR}
24 | )
25 |
26 | install(TARGETS decap
27 | EXPORT katran-exports
28 | DESTINATION decap
29 | )
30 |
31 | if (BUILD_TESTS)
32 | add_subdirectory(testing)
33 | endif()
34 |
--------------------------------------------------------------------------------
/katran/lib/MonitoringStructs.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2004-present Facebook. All Rights Reserved.
2 |
3 | #include "katran/lib/MonitoringStructs.h"
4 |
5 | namespace katran {
6 | namespace monitoring {
7 |
8 | std::set kAllEventIds = {
9 | EventId::TCP_NONSYN_LRUMISS,
10 | EventId::PACKET_TOOBIG,
11 | EventId::QUIC_PACKET_DROP_NO_REAL,
12 | };
13 |
14 | std::string toString(const EventId& eventId) {
15 | switch (eventId) {
16 | case (EventId::TCP_NONSYN_LRUMISS):
17 | return "TCP_NONSYN_LRUMISS";
18 | case (EventId::PACKET_TOOBIG):
19 | return "PACKET_TOOBIG";
20 | case (EventId::QUIC_PACKET_DROP_NO_REAL):
21 | return "QUIC_PACKET_DROP_NO_REAL";
22 | default:
23 | return "UNKOWN";
24 | }
25 | }
26 |
27 | std::ostream& operator<<(std::ostream& os, const EventId& eventId) {
28 | os << toString(eventId);
29 | return os;
30 | }
31 |
32 | } // namespace monitoring
33 | } // namespace katran
34 |
--------------------------------------------------------------------------------
/katran/lib/MurmurHash3.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 |
21 | namespace katran {
22 | uint64_t
23 | MurmurHash3_x64_64(const uint64_t& A, const uint64_t& B, const uint32_t seed);
24 | }
25 |
--------------------------------------------------------------------------------
/katran/decap/Makefile-bpf:
--------------------------------------------------------------------------------
1 | obj := .
2 | src := .
3 |
4 |
5 | DEBUGBPF = -DDEBUG
6 | DEBUGFLAGS = -O0 -g -Wall
7 | PFLAGS = $(DEBUGFLAGS)
8 |
9 | INCLUDEFLAGS = -I$(obj)/usr/include \
10 | -I$(obj)/include \
11 | #-I$(obj)/bpfprog/include \
12 |
13 |
14 |
15 | always = bpf/decap_kern.o
16 |
17 | HOSTCFLAGS += $(INCLUDEFLAGS) $(PFLAGS)
18 |
19 | # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
20 | # make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
21 | LLC ?= llc
22 | CLANG ?= clang
23 |
24 | # Trick to allow make to be run from this directory
25 | all: $(always)
26 | $(MAKE) -C .. $$PWD/
27 |
28 | clean:
29 | $(MAKE) -C .. M=$$PWD clean
30 | @rm -f *~
31 |
32 | $(obj)/bpf/%.o: $(src)/bpf/%.c
33 | $(CLANG) $(INCLUDEFLAGS) $(EXTRA_CFLAGS) \
34 | $(DEBUGBPF) -D__KERNEL__ -Wno-unused-value -Wno-pointer-sign \
35 | -Wno-compare-distinct-pointer-types \
36 | -O2 -emit-llvm -c -g $< -o -| $(LLC) -march=bpf -filetype=obj -o $@
37 |
38 |
--------------------------------------------------------------------------------
/katran/lib/MacHelpers.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | namespace katran {
24 | std::vector convertMacToUint(const std::string& macAddress);
25 | std::string convertMacToString(std::vector mac);
26 | } // namespace katran
27 |
--------------------------------------------------------------------------------
/collect_debug_lb.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Copyright (C) 2019-present, Facebook, Inc.
3 | #
4 | # This program is free software; you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation; version 2 of the License.
7 | #
8 | # This program is distributed in the hope that it will be useful,
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | # GNU General Public License for more details.
12 | #
13 | # You should have received a copy of the GNU General Public License along
14 | # with this program; if not, write to the Free Software Foundation, Inc.,
15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 | echo "### links ###"
17 | ip link show
18 | echo "### default route ###"
19 | ip route show | grep default
20 | echo "### neighbors ###"
21 | ip neighbor show
22 | echo "### ps ###"
23 | ps ax | grep katran
24 | echo "### sysctl ###"
25 | sysctl -a 2>&1 | grep bpf | grep -v denied
26 |
--------------------------------------------------------------------------------
/collect_debug_real.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Copyright (C) 2019-present, Facebook, Inc.
3 | #
4 | # This program is free software; you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation; version 2 of the License.
7 | #
8 | # This program is distributed in the hope that it will be useful,
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | # GNU General Public License for more details.
12 | #
13 | # You should have received a copy of the GNU General Public License along
14 | # with this program; if not, write to the Free Software Foundation, Inc.,
15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 | echo "### links ###"
17 | ip link show
18 | echo "### default route ###"
19 | ip route show | grep default
20 | echo "### neighbors ###"
21 | ip neighbor show
22 | echo "### sysctl ###"
23 | sysctl -a 2>&1 | grep rp_filter | grep -v denied
24 | echo "### iptables ###"
25 | sudo iptables -vnL
26 |
--------------------------------------------------------------------------------
/katran/tpr/bpf/tcp_pkt_router_maps.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #pragma once
4 |
5 | #include "tcp_pkt_router_structs.h"
6 |
7 | /* map to store server related info, such as server-id */
8 | struct {
9 | __uint(type, BPF_MAP_TYPE_ARRAY);
10 | __uint(map_flags, NO_FLAGS);
11 | __uint(max_entries, SERVER_INFO_MAP_SIZE);
12 | __type(key, __u32); // index of the array
13 | __type(value, struct server_info);
14 | } server_infos SEC(".maps");
15 |
16 | /* BPF sk_storage map to store info for each connection */
17 | struct {
18 | __uint(type, BPF_MAP_TYPE_SK_STORAGE);
19 | __uint(map_flags, BPF_F_NO_PREALLOC);
20 | __type(key, __u32); // socket-fd
21 | __type(value, __u32); // 4-bytes server_id
22 | } sk_sid_store SEC(".maps");
23 |
24 | /* map which contains counters for different packet level events for monitoring
25 | * purpose */
26 | struct {
27 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
28 | __uint(map_flags, NO_FLAGS);
29 | __uint(max_entries, STATS_SIZE);
30 | __type(key, __u32); // index of the array
31 | __type(value, struct stats);
32 | } tpr_stats SEC(".maps");
33 |
--------------------------------------------------------------------------------
/katran/tpr/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required (VERSION 3.9)
2 | set(KATRAN_TPR_INCLUDE_DIR "$")
3 |
4 | find_package(Glog REQUIRED)
5 | find_package(folly CONFIG REQUIRED)
6 | find_package(Threads)
7 |
8 | add_subdirectory(bpf_util)
9 |
10 | set(LIBBPF_INCLUDE_DIRS "${LIB_BPF_PREFIX}/include")
11 | set(LIBBPF_LIBRARIES "${LIB_BPF_PREFIX}/lib")
12 | set(BPFOBJECT_VMLINUX_H "bpf/vmlinux/vmlinux.h")
13 | set(BPFOBJECT_BPFTOOL_EXE "${CMAKE_INSTALL_PREFIX}/bin/bpftool")
14 | set(BPFOBJECT_EXTRA_DEFINES "-DKATRAN_CMAKE_BUILD")
15 | find_package(BpfObject REQUIRED)
16 |
17 | bpf_object(tpr_bpf
18 | bpf/tcp_pkt_router.bpf.c
19 |
20 | )
21 |
22 | add_library(katran_tpr STATIC
23 | TPRStatsPoller.cpp
24 | TcpPktRouter.cpp
25 | )
26 |
27 | target_compile_definitions(katran_tpr PUBLIC KATRAN_CMAKE_BUILD=1)
28 |
29 | target_link_libraries(katran_tpr
30 | "Folly::folly"
31 | glog::glog
32 | ${BPF_LINK_LIBRARIES}
33 | tpr_bpf_skel
34 | )
35 |
36 | target_include_directories(
37 | katran_tpr PUBLIC
38 | ${GFLAGS_INCLUDE_DIR}
39 | ${KATRAN_TPR_INCLUDE_DIR}
40 | )
41 |
--------------------------------------------------------------------------------
/katran/lib/PipeWriter.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2004-present Facebook. All Rights Reserved.
2 |
3 | #include "katran/lib/PipeWriter.h"
4 | #include
5 | #include
6 |
7 | namespace katran {
8 | PipeWriter::PipeWriter() {}
9 |
10 | void PipeWriter::writeData(const void* ptr, std::size_t size) {
11 | VLOG_EVERY_N(4, 10) << __func__ << " write " << size << " bytes";
12 |
13 | if (size == 0) {
14 | LOG(ERROR) << "Zero-sized data. Skipping";
15 | return;
16 | }
17 |
18 | if (!enabled_) {
19 | VLOG_EVERY_N(4, 10) << "Disabled pipe writer. Skipping";
20 | return;
21 | }
22 |
23 | pipe_->write(&writeCallback_, ptr, size);
24 | }
25 |
26 | void PipeWriter::writeHeader(const void* ptr, std::size_t size) {
27 | // This could overwrite pre-existing header
28 | headerBuf_ = folly::IOBuf::copyBuffer(ptr, size);
29 | }
30 |
31 | void PipeWriter::setWriterDestination(
32 | std::shared_ptr pipeWriter) {
33 | CHECK(pipeWriter) << "Null pipe writer";
34 | pipe_ = pipeWriter;
35 | }
36 |
37 | void PipeWriter::unsetWriterDestination() {
38 | pipe_.reset();
39 | }
40 | } // namespace katran
41 |
--------------------------------------------------------------------------------
/tools/xdpdump/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.9)
2 | project(xdpdump)
3 | set (CMAKE_CXX_STANDARD 17)
4 |
5 | find_library(LIBBCC bcc)
6 | find_library(DL dl)
7 | find_library(LIBIBERTY libiberty.a iberty)
8 | find_library(EVENT_CORE libevent_core.a event_core)
9 |
10 | add_library(xdp_event_logger
11 | XdpEventLogger.h
12 | XdpEventReader.h
13 | XdpEventReader.cpp
14 | XdpEventLogger.cpp
15 | )
16 |
17 | target_link_libraries(xdp_event_logger
18 | katranlb
19 | pcapwriter
20 | "Folly::folly"
21 | "glog::glog"
22 | )
23 |
24 | add_library(lxdpdump
25 | XdpDump.h
26 | XdpDump.cpp
27 | XdpDumpKern.h
28 | )
29 |
30 | target_link_libraries(lxdpdump
31 | xdp_event_logger
32 | "${LIBELF}"
33 | "${LIBZ}"
34 | "${LIBBCC}"
35 | "Folly::folly"
36 | "glog::glog"
37 | )
38 |
39 | add_executable(xdpdump xdpdump_tool.cpp)
40 | target_link_libraries(xdpdump
41 | "-Wl,--start-group"
42 | "${LIBUNWIND}"
43 | "Folly::folly"
44 | "glog::glog"
45 | "${GFLAGS}"
46 | "${PTHREAD}"
47 | "${LIBDC}"
48 | "${DL}"
49 | "${EVENT_CORE}"
50 | "${LIBIBERTY}"
51 | iphelpers
52 | lxdpdump
53 | "-Wl,--end-group"
54 | )
55 |
--------------------------------------------------------------------------------
/katran/lib/Makefile-bpf:
--------------------------------------------------------------------------------
1 | obj := .
2 | src := .
3 |
4 |
5 | DEBUGBPF = -DDEBUG
6 | DEBUGFLAGS = -O0 -g -Wall
7 | PFLAGS = $(DEBUGFLAGS)
8 |
9 | INCLUDEFLAGS = -I$(obj)/usr/include \
10 | -I$(obj)/include \
11 | -I$(obj)
12 |
13 |
14 |
15 | always = bpf/balancer.bpf.o
16 | always += bpf/healthchecking_ipip.o
17 | always += bpf/healthchecking.bpf.o
18 | always += bpf/xdp_pktcntr.o
19 | always += bpf/xdp_root.o
20 |
21 | HOSTCFLAGS += $(INCLUDEFLAGS) $(PFLAGS)
22 | HOSTCFLAGS_bpf_load.o += $(INCLUDEFLAGS) $(PFLAGS) -Wno-unused-variable
23 |
24 |
25 | # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
26 | # make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
27 | LLC ?= llc
28 | CLANG ?= clang
29 |
30 | # Trick to allow make to be run from this directory
31 | all: $(always)
32 | $(MAKE) -C .. $$PWD/
33 |
34 | clean:
35 | $(MAKE) -C .. M=$$PWD clean
36 | @rm -f *~
37 |
38 | $(obj)/bpf/%.o: $(src)/katran/lib/bpf/%.c
39 | $(CLANG) $(INCLUDEFLAGS) $(EXTRA_CFLAGS) \
40 | $(DEBUGBPF) -D__KERNEL__ -Wno-unused-value -Wno-pointer-sign \
41 | -Wno-compare-distinct-pointer-types \
42 | -O2 -emit-llvm -c -g $< -o -| $(LLC) -march=bpf -filetype=obj -o $@
43 |
--------------------------------------------------------------------------------
/katran/decap/tc_bpf/tc_decap_info_user_structs.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2019-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 | #ifndef __DECAP_INFO_USER_STRUCTS_H
18 | #define __DECAP_INFO_USER_STRUCTS_H
19 |
20 | struct flow_key {
21 | union {
22 | uint32_t src;
23 | uint32_t srcv6[4];
24 | };
25 | union {
26 | uint32_t dst;
27 | uint32_t dstv6[4];
28 | };
29 | union {
30 | uint32_t ports;
31 | uint16_t port16[2];
32 | };
33 | uint8_t proto;
34 | };
35 |
36 | #endif // of __DECAP_INFO_USER_STRUCTS
37 |
--------------------------------------------------------------------------------
/os_run_tester.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (C) 2018-present, Facebook, Inc.
4 | #
5 | # This program 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; version 2 of the License.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License along
15 | # with this program; if not, write to the Free Software Foundation, Inc.,
16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 |
18 | set -xeo pipefail
19 |
20 | # By default this script assumes to be invoked from the root dir.
21 | if [ -z "${KATRAN_BUILD_DIR}" ]
22 | then
23 | KATRAN_BUILD_DIR=$(pwd)/_build/build
24 | fi
25 |
26 | if [ -z "${DEPS_DIR}" ]
27 | then
28 | DEPS_DIR=$(pwd)/_build/deps
29 | fi
30 |
31 | sudo sh -c "${KATRAN_BUILD_DIR}/katran/lib/testing/katran_tester -balancer_prog ${DEPS_DIR}/bpfprog/bpf/balancer.bpf.o -test_from_fixtures=true $1"
32 |
--------------------------------------------------------------------------------
/katran/lib/ByteRangeWriter.cpp:
--------------------------------------------------------------------------------
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 "katran/lib/ByteRangeWriter.h"
18 |
19 | #include
20 |
21 | namespace katran {
22 |
23 | ByteRangeWriter::ByteRangeWriter(folly::MutableByteRange& buffer)
24 | : buffer_(buffer) {}
25 |
26 | void ByteRangeWriter::writeData(const void* ptr, std::size_t size) {
27 | ::memcpy(static_cast(&(buffer_.front())), ptr, size);
28 | buffer_.advance(size);
29 | writtenBytes_ += size;
30 | }
31 |
32 | bool ByteRangeWriter::available(std::size_t amount) {
33 | return buffer_.size() >= amount;
34 | }
35 |
36 | } // namespace katran
37 |
--------------------------------------------------------------------------------
/katran/lib/CHHelpers.cpp:
--------------------------------------------------------------------------------
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 "katran/lib/CHHelpers.h"
18 | #include "katran/lib/MaglevHash.h"
19 | #include "katran/lib/MaglevHashV2.h"
20 | namespace katran {
21 | std::unique_ptr CHFactory::make(HashFunction func) {
22 | switch (func) {
23 | case HashFunction::Maglev:
24 | return std::make_unique();
25 | case HashFunction::MaglevV2:
26 | return std::make_unique();
27 | default:
28 | // fallback to default maglev's implementation
29 | return std::make_unique();
30 | }
31 | }
32 | } // namespace katran
33 |
--------------------------------------------------------------------------------
/katran/lib/bpf/xdp_root.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 "bpf.h"
18 | #include "bpf_helpers.h"
19 |
20 | #define ROOT_ARRAY_SIZE 3
21 |
22 | struct {
23 | __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
24 | __type(key, __u32);
25 | __type(value, __u32);
26 | __uint(max_entries, ROOT_ARRAY_SIZE);
27 | } root_array SEC(".maps");
28 |
29 | SEC("xdp")
30 | int xdp_root(struct xdp_md* ctx) {
31 | __u32* fd;
32 | #pragma clang loop unroll(full)
33 | for (__u32 i = 0; i < ROOT_ARRAY_SIZE; i++) {
34 | bpf_tail_call(ctx, &root_array, i);
35 | }
36 | return XDP_PASS;
37 | }
38 |
39 | char _license[] SEC("license") = "GPL";
40 |
--------------------------------------------------------------------------------
/katran/lib/testing/utils/Base64Test.cpp:
--------------------------------------------------------------------------------
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 |
19 | #include
20 |
21 | #include "katran/lib/testing/utils/Base64Helpers.h"
22 |
23 | namespace katran {
24 |
25 | TEST(Base64Tests, testEncode) {
26 | auto test_string = "Test Data!";
27 | auto buf = folly::IOBuf::copyBuffer(test_string);
28 | ASSERT_STREQ(
29 | Base64Helpers::base64Encode(buf.get()).c_str(), "VGVzdCBEYXRhIQ==");
30 | };
31 |
32 | TEST(Base64Tests, testDecode) {
33 | ASSERT_STREQ(
34 | Base64Helpers::base64Decode("VGVzdCBEYXRhIQ==").c_str(), "Test Data!");
35 | };
36 |
37 | } // namespace katran
38 |
--------------------------------------------------------------------------------
/katran/lib/IOBufWriter.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
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 "katran/lib/IOBufWriter.h"
18 | #include
19 |
20 | namespace katran {
21 |
22 | IOBufWriter::IOBufWriter(folly::IOBuf* iobuf) : iobuf_(iobuf) {}
23 |
24 | void IOBufWriter::writeData(const void* ptr, std::size_t size) {
25 | ::memcpy(static_cast(iobuf_->writableTail()), ptr, size);
26 | iobuf_->append(size);
27 | }
28 |
29 | bool IOBufWriter::available(std::size_t amount) {
30 | return iobuf_->tailroom() >= amount;
31 | }
32 |
33 | bool IOBufWriter::restart() {
34 | iobuf_->clear();
35 | return true;
36 | }
37 |
38 | } // namespace katran
39 |
--------------------------------------------------------------------------------
/katran/lib/tests/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # find libraries
2 | find_library(CHHELPERS chhelpers)
3 | find_path(CHHELPERS_INCLUDE_DIR chhelpers)
4 | include(KatranTest)
5 |
6 | katran_add_test(TARGET iphelpers-tests
7 | SOURCES
8 | IpHelpersTest.cpp
9 | DEPENDS
10 | iphelpers
11 | ${GTEST}
12 | ${PTHREAD}
13 | "Folly::folly"
14 | )
15 |
16 | katran_add_test(TARGET chhelpers-tests
17 | SOURCES
18 | CHHelpersTest.cpp
19 | DEPENDS
20 | katranlb
21 | ${GTEST}
22 | ${PTHREAD}
23 | )
24 |
25 | katran_add_test(TARGET libkatran-tests
26 | SOURCES
27 | KatranLbTest.cpp
28 | DEPENDS
29 | katranlb
30 | ${GTEST}
31 | ${PTHREAD}
32 | "Folly::folly"
33 | )
34 |
35 | katran_add_test(TARGET vip-tests
36 | SOURCES
37 | VipTest.cpp
38 | DEPENDS
39 | katranlb
40 | ${GTEST}
41 | ${PTHREAD}
42 | "Folly::folly"
43 | )
44 |
45 | katran_add_test(TARGET eventpipe-callback-test
46 | SOURCES
47 | EventPipeCallbackTest.cpp
48 | DEPENDS
49 | katranlb
50 | ${GTEST}
51 | ${GMOCK}
52 | ${PTHREAD}
53 | "Folly::folly"
54 | )
55 |
56 | katran_add_test(TARGET monitoring-service-core-test
57 | SOURCES
58 | MonitoringServiceCoreTest.cpp
59 | DEPENDS
60 | katranlb
61 | ${GTEST}
62 | ${PTHREAD}
63 | "Folly::folly"
64 | )
65 |
66 | katran_add_test(TARGET pcap-writer-test
67 | SOURCES
68 | PcapWriterTest.cpp
69 | DEPENDS
70 | katranlb
71 | ${GMOCK}
72 | ${GTEST}
73 | ${PTHREAD}
74 | "Folly::folly"
75 | )
76 |
--------------------------------------------------------------------------------
/katran/tpr/bpf/tcp_pkt_router_structs.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #pragma once
4 |
5 | struct server_info {
6 | // 1 == server, 2 == client
7 | __u8 running_mode;
8 | // 0 = no, otherwise yes
9 | __u8 kde_enabled;
10 | // zones supported by kde
11 | __u8 kde_zones;
12 | __u32 server_id;
13 | // when default server id is not available, backend users server id v2 as
14 | // fallback
15 | __u32 server_id_fallback;
16 | };
17 |
18 | // struct that represents a header options in TCP packet
19 | struct tcp_opt {
20 | __u8 kind;
21 | __u8 len;
22 | __u32 server_id;
23 | } __attribute__((packed));
24 |
25 | // struct that represents an option that, if present in the incoming
26 | // syn from the client, indicates that we shouldn't use TPR.
27 | struct kde_clt_tcp_opt_v2 {
28 | __u8 kind;
29 | __u8 len;
30 | __u8 zone;
31 | } __attribute__((packed));
32 | #define KDE_CLT_TCP_HDR_OPT_LEN 2
33 | #define KDE_CLT_TCP_HDR_OPT_V2_LEN 3
34 |
35 | // stats for different packet events
36 | struct stats {
37 | // TODO: these are tentative fields for now
38 | __u64 server_id_read;
39 | __u64 server_id_set;
40 | __u64 conns_skipped;
41 | __u64 no_tcp_opt_hdr;
42 | __u64 error_bad_id;
43 | __u64 error_server_id_zero;
44 | __u64 error_write_opt;
45 | __u64 error_sys_calls;
46 | __u64 ignoring_due_to_kde;
47 | // stats for the rollout of the new TPR server OPT
48 | __u64 server_opt;
49 | };
50 |
--------------------------------------------------------------------------------
/katran/lib/linux_includes/bpf_common.h:
--------------------------------------------------------------------------------
1 | #ifndef __LINUX_BPF_COMMON_H__
2 | #define __LINUX_BPF_COMMON_H__
3 |
4 | /* Instruction classes */
5 | #define BPF_CLASS(code) ((code) & 0x07)
6 | #define BPF_LD 0x00
7 | #define BPF_LDX 0x01
8 | #define BPF_ST 0x02
9 | #define BPF_STX 0x03
10 | #define BPF_ALU 0x04
11 | #define BPF_JMP 0x05
12 | #define BPF_RET 0x06
13 | #define BPF_MISC 0x07
14 |
15 | /* ld/ldx fields */
16 | #define BPF_SIZE(code) ((code) & 0x18)
17 | #define BPF_W 0x00 /* 32-bit */
18 | #define BPF_H 0x08 /* 16-bit */
19 | #define BPF_B 0x10 /* 8-bit */
20 | /* eBPF BPF_DW 0x18 64-bit */
21 | #define BPF_MODE(code) ((code) & 0xe0)
22 | #define BPF_IMM 0x00
23 | #define BPF_ABS 0x20
24 | #define BPF_IND 0x40
25 | #define BPF_MEM 0x60
26 | #define BPF_LEN 0x80
27 | #define BPF_MSH 0xa0
28 |
29 | /* alu/jmp fields */
30 | #define BPF_OP(code) ((code) & 0xf0)
31 | #define BPF_ADD 0x00
32 | #define BPF_SUB 0x10
33 | #define BPF_MUL 0x20
34 | #define BPF_DIV 0x30
35 | #define BPF_OR 0x40
36 | #define BPF_AND 0x50
37 | #define BPF_LSH 0x60
38 | #define BPF_RSH 0x70
39 | #define BPF_NEG 0x80
40 | #define BPF_MOD 0x90
41 | #define BPF_XOR 0xa0
42 |
43 | #define BPF_JA 0x00
44 | #define BPF_JEQ 0x10
45 | #define BPF_JGT 0x20
46 | #define BPF_JGE 0x30
47 | #define BPF_JSET 0x40
48 | #define BPF_SRC(code) ((code) & 0x08)
49 | #define BPF_K 0x00
50 | #define BPF_X 0x08
51 |
52 | #ifndef BPF_MAXINSNS
53 | #define BPF_MAXINSNS 4096
54 | #endif
55 |
56 | #endif /* __LINUX_BPF_COMMON_H__ */
57 |
--------------------------------------------------------------------------------
/katran/tpr/bpf/tcp_pkt_router_consts.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #pragma once
4 |
5 | /* size of stats map */
6 | #define STATS_SIZE 1
7 |
8 | /* position in stats map where we store generic counters */
9 | #define GENERIC_STATS_INDEX 0
10 |
11 | /* position in stats map where we store server_info */
12 | #define SERVER_INFO_INDEX 0
13 |
14 | /*
15 | * Currently, servers use TCP_HDR_OPT_KIND, but we'll be migrating them
16 | * to use TCP_SRV_HDR_OPT_KIND because we want the server and client to
17 | * use different OPTs.
18 | */
19 | #define TCP_SRV_HDR_OPT_KIND 0xB6
20 |
21 | /* Reserved hdr-opt-value for this case.
22 | * Picked random unused value from IANA TCP Option Kind Numbers
23 | */
24 | #define TCP_HDR_OPT_KIND 0xB7
25 |
26 | /*
27 | * We don't insert the TPR opt on the server side if this opt is present
28 | * in the client's SYN
29 | */
30 | #define KDE_CLT_TCP_HDR_OPT_KIND 0xB8
31 |
32 | /* 4 bytes len for the server-id in TCP_HDR_OPT + KIND and LEN */
33 | #define TCP_HDR_OPT_LEN 6
34 |
35 | /* For consistent handling of success vs failues */
36 | #define CG_OK 1
37 | #define CG_ERR 0
38 |
39 | /* value to represent the 'server' side */
40 | #define SERVER_MODE 1
41 | #define CLIENT_MODE 2
42 |
43 | /* Server info map has only 1 item */
44 | #define SERVER_INFO_MAP_SIZE 1
45 |
46 | #define TCPHDR_SYN 0x02
47 | #define TCPHDR_ACK 0x10
48 | #define TCPHDR_SYNACK (TCPHDR_SYN | TCPHDR_ACK)
49 |
50 | #define NO_FLAGS 0
51 | #define SUCCESS 0
52 | #define PASS -1
53 |
--------------------------------------------------------------------------------
/katran/lib/FileWriter.h:
--------------------------------------------------------------------------------
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 | #pragma once
17 |
18 | #include
19 | #include
20 |
21 | #include "katran/lib/DataWriter.h"
22 |
23 | namespace katran {
24 | /**
25 | * FileWriter is used to write pcap-data into file.
26 | */
27 | class FileWriter : public DataWriter {
28 | public:
29 | /**
30 | * @param const string filename where we are going to write data
31 | */
32 | explicit FileWriter(const std::string& filename);
33 |
34 | void writeData(const void* ptr, std::size_t size) override;
35 |
36 | bool available(std::size_t amount) override;
37 |
38 | bool restart() override;
39 |
40 | bool stop() override;
41 |
42 | private:
43 | folly::File pcapFile_;
44 | std::string filename_;
45 | };
46 |
47 | } // namespace katran
48 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | name: 'Close stale issues and PRs'
2 | on:
3 | schedule:
4 | - cron: '0 12 * * 1-5' # every weekday at noon
5 |
6 | jobs:
7 | stale:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/stale@v8
11 | with:
12 | stale-issue-message: >
13 | This issue has been automatically marked as stale because it has not had
14 | recent activity. If you'd still having this issue please make a comment,
15 | make sure you've addressed any follow ups!
16 | stale-pr-message: >
17 | This pull request has been automatically marked as stale because it has not had
18 | recent activity. If you'd still like this PR merged, please comment on the PR,
19 | make sure you've addressed reviewer comments, and rebase on the latest main.
20 | Thank you for your contributions!
21 | close-issue-message: >
22 | This issue has been closed because it has not had recent activity. If you are
23 | still having this issue please feel free to create a new one.
24 | close-pr-message: >
25 | This pull request has been automatically closed it has not had
26 | recent activity. If you'd still like this PR merged, please feel free to reopen it,
27 | make sure you've addressed reviewer comments, and rebase on the latest main.
28 | Thank you for your contributions!
29 | days-before-stale: 90 # ~ 3 months
30 | days-before-close: 14
31 |
--------------------------------------------------------------------------------
/katran/lib/bpf/flow_debug.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
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 | #ifndef __FLOW_DEBUG_H
18 | #define __FLOW_DEBUG_H
19 |
20 | #ifdef RECORD_FLOW_INFO
21 |
22 | #ifndef FLOW_DEBUG_MAP_SIZE
23 | #define FLOW_DEBUG_MAP_SIZE 1000000
24 | #endif // of FLOW_DEBUG_MAP_SIZE
25 |
26 | #define NO_FLAGS 0
27 |
28 | #include "katran/lib/bpf/flow_debug_helpers.h"
29 |
30 | // Flow debug enabled, enable helpers
31 | #define RECORD_GUE_ROUTE(old_eth, new_eth, data_end, outer_v4, inner_v4) \
32 | gue_record_route(old_eth, new_eth, data_end, outer_v4, inner_v4)
33 |
34 | #else
35 |
36 | // Flow debug disabled, define helpers to be noop
37 | #define RECORD_GUE_ROUTE(...) \
38 | { \
39 | }
40 |
41 | #endif // of RECORD_FLOW_INFO
42 |
43 | #endif // of __FLOW_DEBUG_H
44 |
--------------------------------------------------------------------------------
/start_katran_grpc_server.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (C) 2018-present, Facebook, Inc.
4 | #
5 | # This program 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; version 2 of the License.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License along
15 | # with this program; if not, write to the Free Software Foundation, Inc.,
16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 |
18 | # this script will start simple_katran_server w/ xdproot
19 | set -xeo pipefail
20 |
21 | if [ -z "${KATRAN_INTERFACE}" ]
22 | then
23 | KATRAN_INTERFACE=enp0s3
24 | fi
25 |
26 | # By default this script assumes to be invoked from the root dir.
27 | if [ -z "${KATRAN_BUILD_DIR}" ]
28 | then
29 | KATRAN_BUILD_DIR=$(pwd)/_build/build
30 | fi
31 |
32 | if [ -z "${DEPS_DIR}" ]
33 | then
34 | DEPS_DIR=$(pwd)/_build/deps
35 | fi
36 |
37 | ./install_xdproot.sh -b "${KATRAN_BUILD_DIR}" -d "${DEPS_DIR}"
38 | sudo sh -c "${KATRAN_BUILD_DIR}/example_grpc/katran_server_grpc -balancer_prog=${DEPS_DIR}/bpfprog/bpf/balancer.bpf.o -intf=${KATRAN_INTERFACE} -hc_forwarding=false -map_path=/sys/fs/bpf/jmp_${KATRAN_INTERFACE} -prog_pos=2"
39 |
--------------------------------------------------------------------------------
/start_katran_simple_server.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (C) 2018-present, Facebook, Inc.
4 | #
5 | # This program 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; version 2 of the License.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License along
15 | # with this program; if not, write to the Free Software Foundation, Inc.,
16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 |
18 | # this script will start simple_katran_server w/ xdproot
19 | set -xeo pipefail
20 |
21 | if [ -z "${KATRAN_INTERFACE}" ]
22 | then
23 | KATRAN_INTERFACE=enp0s3
24 | fi
25 |
26 | # By default this script assumes to be invoked from the root dir.
27 | if [ -z "${KATRAN_BUILD_DIR}" ]
28 | then
29 | KATRAN_BUILD_DIR=$(pwd)/_build/build
30 | fi
31 |
32 | if [ -z "${DEPS_DIR}" ]
33 | then
34 | DEPS_DIR=$(pwd)/_build/deps
35 | fi
36 |
37 | ./install_xdproot.sh -b "${KATRAN_BUILD_DIR}" -d "${DEPS_DIR}"
38 | sudo sh -c "${KATRAN_BUILD_DIR}/example/simple_katran_server -balancer_prog=${DEPS_DIR}/bpfprog/bpf/balancer.bpf.o -intf=${KATRAN_INTERFACE} -hc_forwarding=false -map_path=/sys/fs/bpf/jmp_${KATRAN_INTERFACE} -prog_pos=2"
39 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to katran
2 | We want to make contributing to this project as easy and transparent as
3 | possible.
4 |
5 | ## Pull Requests
6 | We actively welcome your pull requests.
7 |
8 | 1. Fork the repo and create your branch from `main`.
9 | 2. If you've added code that should be tested, add tests.
10 | 3. If you've changed APIs, update the documentation.
11 | 4. Ensure the test suite passes.
12 | 5. Make sure your code lints.
13 | 6. If you haven't already, complete the Contributor License Agreement ("CLA").
14 |
15 | ## Contributor License Agreement ("CLA")
16 | In order to accept your pull request, we need you to submit a CLA. You only need
17 | to do this once to work on any of Facebook's open source projects.
18 |
19 | Complete your CLA here:
20 |
21 | ## Issues
22 | We use GitHub issues to track public bugs. Please ensure your description is
23 | clear and has sufficient instructions to be able to reproduce the issue.
24 |
25 | Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
26 | disclosure of security bugs. In those cases, please go through the process
27 | outlined on that page and do not file a public issue.
28 |
29 | ## Coding Style
30 | we are using clang-format tool for coding style. please
31 | run `clang-format -i ` on file, where changes has been made, before
32 | you commit them.
33 | ## License
34 | By contributing to katran, you agree that your contributions will be licensed
35 | under the LICENSE file in the root directory of this source tree.
36 |
--------------------------------------------------------------------------------
/katran/decap/tc_bpf/tc_decap_info_maps.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2019-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 | #ifndef __DECAP_INFO_MAPS_H
18 | #define __DECAP_INFO_MAPS_H
19 |
20 | /*
21 | * This file contains definition of all maps which has been used by balancer
22 | */
23 | #include "katran/lib/bpf/balancer_consts.h"
24 | #include "katran/lib/bpf/balancer_structs.h"
25 | #include "katran/lib/linux_includes/bpf.h"
26 | #include "katran/lib/linux_includes/bpf_helpers.h"
27 |
28 | #ifndef PCKT_INFO_MAP_SIZE
29 | #define PCKT_INFO_MAP_SIZE 100000
30 | #endif
31 |
32 | struct {
33 | __uint(type, BPF_MAP_TYPE_LRU_HASH);
34 | __type(key, struct flow_key);
35 | __type(value, struct flow_key);
36 | __uint(max_entries, PCKT_INFO_MAP_SIZE);
37 | __uint(map_flags, NO_FLAGS);
38 | } pkt_encap_info SEC(".maps");
39 |
40 | #endif // of _DECAP_INFO_MAPS
41 |
--------------------------------------------------------------------------------
/katran/lib/bpf/healthchecking_structs.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
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 | #ifndef __HEALTHCHECKING_STRUCTS_H
18 | #define __HEALTHCHECKING_STRUCTS_H
19 |
20 | struct hc_real_definition {
21 | union {
22 | __be32 daddr;
23 | __be32 v6daddr[4];
24 | };
25 | __u8 flags;
26 | };
27 |
28 | // struct to record packet level for counters for relevant events
29 | struct hc_stats {
30 | __u64 pckts_processed;
31 | __u64 pckts_dropped;
32 | __u64 pckts_skipped;
33 | __u64 pckts_too_big;
34 | };
35 |
36 | // hc_key's definition
37 | struct hc_key {
38 | union {
39 | __be32 addr;
40 | __be32 addrv6[4];
41 | };
42 | __u16 port;
43 | __u8 proto;
44 | };
45 |
46 | // struct to store mac address
47 | struct hc_mac {
48 | __u8 mac[6];
49 | };
50 |
51 | #endif // of __HEALTHCHECKING_STRUCTS_H
52 |
--------------------------------------------------------------------------------
/katran/lib/IOBufWriter.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
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 | #pragma once
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | #include "katran/lib/DataWriter.h"
23 |
24 | namespace katran {
25 |
26 | /**
27 | * IOBufWriter is used to write pcap-data into IOBuf.
28 | */
29 | class IOBufWriter : public DataWriter {
30 | public:
31 | /**
32 | * @param unique_ptr iobuf for packets to written into
33 | */
34 | explicit IOBufWriter(folly::IOBuf* iobuf);
35 |
36 | void writeData(const void* ptr, std::size_t size) override;
37 |
38 | bool available(std::size_t amount) override;
39 |
40 | bool restart() override;
41 |
42 | bool stop() override {
43 | return true;
44 | }
45 |
46 | private:
47 | folly::IOBuf* iobuf_;
48 | };
49 |
50 | } // namespace katran
51 |
--------------------------------------------------------------------------------
/katran/lib/PcapMsg.cpp:
--------------------------------------------------------------------------------
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 "katran/lib/PcapMsg.h"
18 |
19 | namespace katran {
20 |
21 | PcapMsg::PcapMsg() {
22 | pckt_ = nullptr;
23 | }
24 |
25 | PcapMsg::PcapMsg(const char* pckt, uint32_t origLen, uint32_t capturedLen)
26 | : origLen_(origLen), capturedLen_(capturedLen) {
27 | if (pckt != nullptr) {
28 | pckt_ = folly::IOBuf::copyBuffer(pckt, capturedLen);
29 | }
30 | }
31 |
32 | PcapMsg::~PcapMsg() {}
33 |
34 | PcapMsg& PcapMsg::operator=(PcapMsg&& msg) noexcept {
35 | pckt_ = std::move(msg.pckt_);
36 | origLen_ = msg.origLen_;
37 | capturedLen_ = msg.capturedLen_;
38 | return *this;
39 | }
40 |
41 | PcapMsg::PcapMsg(PcapMsg&& msg) noexcept
42 | : pckt_(std::move(msg.pckt_)),
43 | origLen_(msg.origLen_),
44 | capturedLen_(msg.capturedLen_) {}
45 | } // namespace katran
46 |
--------------------------------------------------------------------------------
/cmake/katran-config.cmake.in:
--------------------------------------------------------------------------------
1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
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 | # This module sets the following variables:
18 | # katran_FOUND
19 | # katran_INCLUDE_DIRS
20 | #
21 | # This module exports targets such as:
22 | # katran::bpfadapter
23 | #
24 | # which can be used with target_link_libraries()
25 |
26 | @PACKAGE_INIT@
27 |
28 | include(CMakeFindDependencyMacro)
29 | find_dependency(folly)
30 | find_dependency(Fizz)
31 | find_dependency(Threads)
32 | find_dependency(Glog)
33 | find_dependency(Gflags)
34 | find_dependency(Bpf)
35 |
36 | if(NOT TARGET katran::bpfadapter)
37 | include("${CMAKE_CURRENT_LIST_DIR}/katran-targets.cmake")
38 | get_target_property(katran_INCLUDE_DIRS katran::bpfadapter INTERFACE_INCLUDE_DIRECTORIES)
39 | endif()
40 |
41 | if(NOT katran_FIND_QUIETLY)
42 | message(STATUS "Found katran: ${PACKAGE_PREFIX_DIR}")
43 | endif()
44 |
--------------------------------------------------------------------------------
/katran/lib/ByteRangeWriter.h:
--------------------------------------------------------------------------------
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 | #pragma once
17 |
18 | #include
19 | #include
20 |
21 | #include "katran/lib/DataWriter.h"
22 |
23 | namespace katran {
24 |
25 | /**
26 | * ByteRangeWriter is used to write pcap-data into MutableByteRange.
27 | */
28 |
29 | class ByteRangeWriter : public DataWriter {
30 | public:
31 | /**
32 | * @param MutableByteRange buffer for packets to written into
33 | */
34 | explicit ByteRangeWriter(folly::MutableByteRange& buffer);
35 |
36 | void writeData(const void* ptr, std::size_t size) override;
37 |
38 | bool available(std::size_t amount) override;
39 |
40 | bool restart() override {
41 | return true;
42 | }
43 |
44 | bool stop() override {
45 | return true;
46 | }
47 |
48 | private:
49 | folly::MutableByteRange& buffer_;
50 | };
51 |
52 | } // namespace katran
53 |
--------------------------------------------------------------------------------
/katran/decap/tc_bpf/tc_decap_maps.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2019-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 | #ifndef __DECAP_MAPS_H
18 | #define __DECAP_MAPS_H
19 |
20 | /*
21 | * This file contains definition of all maps which has been used by balancer
22 | */
23 |
24 | #include "katran/lib/linux_includes/bpf.h"
25 | #include "katran/lib/linux_includes/bpf_helpers.h"
26 |
27 | #include "katran/lib/bpf/balancer_consts.h"
28 |
29 | #ifndef DECAP_STATS_MAP_SIZE
30 | #define DECAP_STATS_MAP_SIZE 1
31 | #endif
32 |
33 | struct decap_stats {
34 | __u64 decap_v4;
35 | __u64 decap_v6;
36 | __u64 total;
37 | };
38 |
39 | // map w/ per vip statistics
40 | struct {
41 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
42 | __type(key, __u32);
43 | __type(value, struct decap_stats);
44 | __uint(max_entries, DECAP_STATS_MAP_SIZE);
45 | __uint(map_flags, NO_FLAGS);
46 | } decap_counters SEC(".maps");
47 |
48 | #endif // of _DECAP_MAPS
49 |
--------------------------------------------------------------------------------
/katran/lib/tests/common/TestMain.cpp:
--------------------------------------------------------------------------------
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 |
19 | #include
20 | #include
21 | #include
22 |
23 | /*
24 | * This is the recommended main function for all tests.
25 | * The Makefile links it into all of the test programs so that tests do not need
26 | * to - and indeed should typically not - define their own main() functions
27 | */
28 | FOLLY_ATTR_WEAK int main(int argc, char** argv);
29 |
30 | int main(int argc, char** argv) {
31 | #if FOLLY_HAVE_LIBGFLAGS
32 | // Enable glog logging to stderr by default.
33 | gflags::SetCommandLineOptionWithMode(
34 | "logtostderr", "1", gflags::SET_FLAGS_DEFAULT);
35 | #endif
36 |
37 | ::testing::InitGoogleTest(&argc, argv);
38 | folly::Init init(&argc, &argv);
39 |
40 | return RUN_ALL_TESTS();
41 | }
42 |
--------------------------------------------------------------------------------
/tools/wireshark/guev1.lua:
--------------------------------------------------------------------------------
1 | -- Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
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 | -- wireshark dissector for GUE variant 1
17 |
18 | do
19 | local ip = Dissector.get("ip")
20 | local ipv6 = Dissector.get("ipv6")
21 |
22 | local guev1 = Proto("guev1", "GUE variant 1")
23 | local proto = ProtoField.new("Protocol", "guev1.proto", ftypes.UINT8, nil, base.DEC, 0xF0)
24 | guev1.fields = {proto}
25 |
26 | local proto_field = Field.new("guev1.proto")
27 |
28 | function guev1.dissector(tvb, pinfo, tree)
29 | pinfo.cols.protocol:set("GUEv1")
30 |
31 | local subtree = tree:add(guev1, tvb(0,1))
32 | subtree:add(proto, tvb(0,1))
33 |
34 | if proto_field()() == 6 then
35 | ipv6:call(tvb, pinfo, tree)
36 | else
37 | ip:call(tvb, pinfo, tree)
38 | end
39 | end
40 |
41 | local udp_table = DissectorTable.get("udp.port")
42 | udp_table:add(6080, guev1)
43 | end
44 |
--------------------------------------------------------------------------------
/katran/lib/MaglevBase.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This program is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License as published by
4 | * the Free Software Foundation; version 2 of the License.
5 | *
6 | * This program is distributed in the hope that it will be useful,
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | * GNU General Public License for more details.
10 | *
11 | * You should have received a copy of the GNU General Public License along
12 | * with this program; if not, write to the Free Software Foundation, Inc.,
13 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14 | */
15 |
16 | #include "katran/lib/MaglevBase.h"
17 | #include "katran/lib/MurmurHash3.h"
18 |
19 | namespace katran {
20 |
21 | namespace {
22 | constexpr uint32_t kHashSeed0 = 0;
23 | constexpr uint32_t kHashSeed1 = 2307;
24 | constexpr uint32_t kHashSeed2 = 42;
25 | constexpr uint32_t kHashSeed3 = 2718281828;
26 | } // namespace
27 |
28 | void MaglevBase::genMaglevPermutation(
29 | std::vector& permutation,
30 | const Endpoint& endpoint,
31 | const uint32_t pos,
32 | const uint32_t ring_size) {
33 | auto offset_hash = MurmurHash3_x64_64(endpoint.hash, kHashSeed2, kHashSeed0);
34 |
35 | auto offset = offset_hash % ring_size;
36 |
37 | auto skip_hash = MurmurHash3_x64_64(endpoint.hash, kHashSeed3, kHashSeed1);
38 |
39 | auto skip = (skip_hash % (ring_size - 1)) + 1;
40 |
41 | permutation[2 * pos] = offset;
42 | permutation[2 * pos + 1] = skip;
43 | }
44 |
45 | } // namespace katran
46 |
--------------------------------------------------------------------------------
/katran/lib/KatranEventReader.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include "katran/lib/PcapMsgMeta.h"
21 | #include "katran/lib/PerfBufferEventReader.h"
22 |
23 | namespace folly {
24 | class EventBase;
25 | }
26 |
27 | namespace katran {
28 | class KatranEventReader : public PerfBufferEventReader {
29 | public:
30 | explicit KatranEventReader(
31 | std::shared_ptr> queue)
32 | : queue_(queue) {}
33 |
34 | /**
35 | * @param int cpu
36 | * @param const char* data received from the XDP prog.
37 | * @param size_t size of the data chunk
38 | */
39 | void handlePerfBufferEvent(int cpu, const char* data, size_t size) noexcept
40 | override;
41 |
42 | private:
43 | /**
44 | * queue toward PcapWriter
45 | */
46 | std::shared_ptr> queue_;
47 | };
48 | } // namespace katran
49 |
--------------------------------------------------------------------------------
/katran/lib/PcapStructs.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | namespace katran {
20 |
21 | // reference to headers format:
22 | // https://wiki.wireshark.org/Development/LibpcapFileFormat
23 | struct pcap_hdr_s {
24 | uint32_t magic_number; /* magic number */
25 | uint16_t version_major; /* major version number */
26 | uint16_t version_minor; /* minor version number */
27 | int32_t thiszone; /* GMT to local correction */
28 | uint32_t sigfigs; /* accuracy of timestamps */
29 | uint32_t snaplen; /* max length of captured packets, in octets */
30 | uint32_t network; /* data link type */
31 | };
32 |
33 | struct pcaprec_hdr_s {
34 | uint32_t ts_sec; /* timestamp seconds */
35 | uint32_t ts_usec; /* timestamp microseconds */
36 | uint32_t incl_len; /* number of octets of packet saved in file */
37 | uint32_t orig_len; /* actual length of packet */
38 | };
39 |
40 | } // namespace katran
41 |
--------------------------------------------------------------------------------
/tools/xdpdump/XdpEventReader.cpp:
--------------------------------------------------------------------------------
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 "tools/xdpdump/XdpEventReader.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | namespace xdpdump {
25 |
26 | void XdpEventReader::handlePerfBufferEvent(
27 | int /* cpu */,
28 | const char* data,
29 | size_t /* size */) noexcept {
30 | auto info = eventLogger_->handlePerfEvent(data);
31 | if (queue_ != nullptr) {
32 | katran::PcapMsg pcap_msg(
33 | data + info.hdr_size, info.pkt_size, info.data_len);
34 | // best effort non blocking write. if writer thread is full we will lose
35 | // this packet
36 | auto res = queue_->write(std::move(pcap_msg));
37 | if (!res) {
38 | // queue is full and we wasnt able to write into it.
39 | ++queueFull_;
40 | }
41 | }
42 | }
43 |
44 | } // namespace xdpdump
45 |
--------------------------------------------------------------------------------
/katran/lib/bpf/flow_debug_maps.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
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 | #ifndef __FLOW_DEBUG_MAPS_H
18 | #define __FLOW_DEBUG_MAPS_H
19 |
20 | #include "katran/lib/linux_includes/bpf.h"
21 | #include "katran/lib/linux_includes/bpf_helpers.h"
22 |
23 | #include "katran/lib/bpf/balancer_structs.h"
24 | #include "katran/lib/bpf/flow_debug.h"
25 |
26 | struct {
27 | __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
28 | __type(key, __u32);
29 | __type(value, __u32);
30 | __uint(max_entries, MAX_SUPPORTED_CPUS);
31 | __uint(map_flags, NO_FLAGS);
32 | __array(
33 | values,
34 | struct {
35 | __uint(type, BPF_MAP_TYPE_LRU_HASH);
36 | __uint(key_size, sizeof(struct flow_key));
37 | __uint(value_size, sizeof(struct flow_debug_info));
38 | __uint(max_entries, DEFAULT_LRU_SIZE);
39 | });
40 | } flow_debug_maps SEC(".maps");
41 |
42 | #endif // of __FLOW_DEBUG_MAPS_H
43 |
--------------------------------------------------------------------------------
/install_xdproot.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (C) 2018-present, Facebook, Inc.
4 | #
5 | # This program 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; version 2 of the License.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License along
15 | # with this program; if not, write to the Free Software Foundation, Inc.,
16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 |
18 | # Example script to start and run xdproot program
19 | set -xeo pipefail
20 |
21 | if [ -z "${KATRAN_INTERFACE}" ]
22 | then
23 | KATRAN_INTERFACE=enp0s3
24 | fi
25 |
26 | out=$(mount | grep bpffs) || true
27 | if [ -z "$out" ]; then
28 | sudo mount -t bpf bpffs /sys/fs/bpf/
29 | fi
30 |
31 | # By default this script assumes to be invoked from the root dir.
32 | if [ -z "${KATRAN_BUILD_DIR}" ]
33 | then
34 | KATRAN_BUILD_DIR=$(pwd)/_build/build
35 | fi
36 |
37 | if [ -z "${DEPS_DIR}" ]
38 | then
39 | DEPS_DIR=$(pwd)/_build/deps
40 | fi
41 |
42 | if [ ! -f "/sys/fs/bpf/jmp_${KATRAN_INTERFACE}" ]; then
43 | echo "Assuming ${KATRAN_INTERFACE} exists. please change script to actual interface if it does not"
44 | sudo sh -c "${KATRAN_BUILD_DIR}/katran/lib/xdproot -bpfprog ${DEPS_DIR}/bpfprog/bpf/xdp_root.o -bpfpath=/sys/fs/bpf/jmp_${KATRAN_INTERFACE} -intf=${KATRAN_INTERFACE}"
45 | fi
46 |
--------------------------------------------------------------------------------
/tools/xdpdump/XdpDumpStructs.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 | #include
19 |
20 | namespace xdpdump {
21 |
22 | struct XdpDumpFilter {
23 | union {
24 | uint32_t src;
25 | uint32_t srcv6[4];
26 | };
27 | union {
28 | uint32_t dst;
29 | uint32_t dstv6[4];
30 | };
31 | uint16_t sport;
32 | uint16_t dport;
33 | uint8_t proto;
34 | bool ipv6;
35 | uint16_t offset;
36 | uint16_t offset_len;
37 | uint32_t pattern;
38 | std::string map_path;
39 | uint8_t flags;
40 | uint64_t count;
41 | bool mute;
42 | int32_t cpu;
43 | int32_t pages;
44 | };
45 |
46 | extern "C" {
47 | struct XdpDumpOutput {
48 | union {
49 | uint32_t src;
50 | uint32_t srcv6[4];
51 | };
52 | union {
53 | uint32_t dst;
54 | uint32_t dstv6[4];
55 | };
56 | bool ipv6;
57 | uint16_t sport;
58 | uint16_t dport;
59 | uint8_t proto;
60 | uint16_t pkt_size;
61 | uint16_t data_len;
62 | };
63 | }
64 | } // namespace xdpdump
65 |
--------------------------------------------------------------------------------
/katran/lib/testing/utils/Base64Helpers.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 |
21 | namespace folly {
22 | class IOBuf;
23 | }
24 |
25 | namespace katran {
26 |
27 | /**
28 | * helper class to do base64 encoding/decoding.
29 | * built to be as simple as possible. only intented to be used in BpfTester
30 | */
31 | class Base64Helpers {
32 | public:
33 | /**
34 | * @param IOBuf* buf pointer to memory, which we want to encode
35 | * @return string base64 encoded memory region, where buf was pointing to
36 | *
37 | * helper function to encode data, stored in IOBuf as base64 encoded string
38 | */
39 | static std::string base64Encode(folly::IOBuf* buf);
40 |
41 | /**
42 | * @param string encoded base64 encoded value
43 | * @return string decoded value
44 | *
45 | * helper function to decode base64 encoded string
46 | */
47 | static std::string base64Decode(std::string encoded);
48 | };
49 |
50 | } // namespace katran
51 |
--------------------------------------------------------------------------------
/katran/lib/MaglevHashV2.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This program is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License as published by
4 | * the Free Software Foundation; version 2 of the License.
5 | *
6 | * This program is distributed in the hope that it will be useful,
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | * GNU General Public License for more details.
10 | *
11 | * You should have received a copy of the GNU General Public License along
12 | * with this program; if not, write to the Free Software Foundation, Inc.,
13 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14 | */
15 |
16 | #pragma once
17 |
18 | #include
19 | #include
20 |
21 | #include "katran/lib/MaglevBase.h"
22 |
23 | namespace katran {
24 |
25 | /**
26 | * MaglevHashV2 class implements another version of Maglev's hash which does not
27 | * require the sum of all weights to be equal to the size of the hash ring.
28 | */
29 | class MaglevHashV2 : public MaglevBase {
30 | public:
31 | MaglevHashV2() {}
32 | /**
33 | * @param std::vector& endpoints, which will be used for CH
34 | * @param uint32_t ring_size size of the CH ring
35 | * @return std::vector vector, which describe CH ring.
36 | * it's size would be ring_size and
37 | * which will have Endpoints.num as a values.
38 | * ring_size must be prime number.
39 | * this function could throw because allocation for vector could fail.
40 | */
41 | std::vector generateHashRing(
42 | std::vector,
43 | const uint32_t ring_size = kDefaultChRingSize) override;
44 | };
45 |
46 | } // namespace katran
47 |
--------------------------------------------------------------------------------
/katran/lib/MaglevHash.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2020-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 | #pragma once
18 |
19 | #include
20 | #include
21 |
22 | #include "katran/lib/MaglevBase.h"
23 |
24 | namespace katran {
25 |
26 | /**
27 | * MaglevHash class implements Maglev's hash algo
28 | * (more info: http://research.google.com/pubs/pub44824.html ; section 3.4)
29 | */
30 | class MaglevHash : public MaglevBase {
31 | public:
32 | MaglevHash() {}
33 | /**
34 | * @param std::vector& endpoints, which will be used for CH
35 | * @param uint32_t ring_size size of the CH ring
36 | * @return std::vector vector, which describe CH ring.
37 | * it's size would be ring_size and
38 | * which will have Endpoints.num as a values.
39 | * ring_size must be prime number.
40 | * this function could throw because allocation for vector could fail.
41 | */
42 | std::vector generateHashRing(
43 | std::vector,
44 | const uint32_t ring_size = kDefaultChRingSize) override;
45 | };
46 |
47 | } // namespace katran
48 |
--------------------------------------------------------------------------------
/katran/lib/FileWriter.cpp:
--------------------------------------------------------------------------------
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 "katran/lib/FileWriter.h"
18 | #include
19 | #include
20 |
21 | namespace katran {
22 |
23 | FileWriter::FileWriter(const std::string& filename)
24 | : pcapFile_(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC) {
25 | filename_ = filename;
26 | }
27 |
28 | void FileWriter::writeData(const void* ptr, std::size_t size) {
29 | auto successfullyWritten = folly::writeFull(pcapFile_.fd(), ptr, size);
30 | if (successfullyWritten < 0) {
31 | LOG(ERROR) << "Error while trying to write to pcap file: " << filename_;
32 | } else {
33 | writtenBytes_ += size;
34 | }
35 | }
36 |
37 | bool FileWriter::available(size_t /* unused */) {
38 | return true;
39 | }
40 |
41 | bool FileWriter::stop() {
42 | pcapFile_.closeNoThrow();
43 | return true;
44 | }
45 |
46 | bool FileWriter::restart() {
47 | pcapFile_.closeNoThrow();
48 | pcapFile_ = folly::File(filename_.c_str(), O_RDWR | O_CREAT | O_TRUNC);
49 | return true;
50 | }
51 |
52 | } // namespace katran
53 |
--------------------------------------------------------------------------------
/katran/lib/KatranEventReader.cpp:
--------------------------------------------------------------------------------
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 | #include "katran/lib/KatranEventReader.h"
17 |
18 | #include "katran/lib/BalancerStructs.h"
19 |
20 | namespace katran {
21 |
22 | void KatranEventReader::handlePerfBufferEvent(
23 | int /* cpu */,
24 | const char* data,
25 | size_t size) noexcept {
26 | if (size < sizeof(struct event_metadata)) {
27 | LOG(ERROR) << "size " << size
28 | << " is less than sizeof(struct event_metadata) "
29 | << sizeof(struct event_metadata) << ", skipping";
30 | return;
31 | }
32 | auto mdata = (struct event_metadata*)data;
33 | PcapMsg pcap_msg(
34 | data + sizeof(struct event_metadata), mdata->pkt_size, mdata->data_len);
35 | PcapMsgMeta pcap_msg_meta(std::move(pcap_msg), mdata->event);
36 | auto res = queue_->write(std::move(pcap_msg_meta));
37 | if (!res) {
38 | LOG(ERROR) << "writer queue is full";
39 | }
40 | LOG(INFO) << __func__
41 | << "write perf event to queue, queue stats: " << queue_->size()
42 | << "/" << queue_->capacity();
43 | }
44 |
45 | } // namespace katran
46 |
--------------------------------------------------------------------------------
/example_grpc/GrpcSignalHandler.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 |
21 | #include
22 | #include
23 |
24 | namespace folly {
25 | class EventBase;
26 | }
27 |
28 | namespace lb {
29 | namespace katran {
30 |
31 | /**
32 | * class which implements sighandler for katran's grpc server
33 | */
34 | class GrpcSignalHandler : public folly::AsyncSignalHandler {
35 | public:
36 | /**
37 | * @param EventBase* evb event base thread
38 | * @param grpc::Server* server katran's grpc server
39 | * @param int32_t delay in ms between recving signal and stopping katran
40 | */
41 | GrpcSignalHandler(
42 | std::shared_ptr evb,
43 | grpc::Server* server,
44 | int32_t delay);
45 | ~GrpcSignalHandler() override {}
46 |
47 | void signalReceived(int signum) noexcept override;
48 |
49 | private:
50 | grpc::Server* server_;
51 | std::shared_ptr evb_;
52 | int32_t delay_;
53 | bool shutdownScheduled_{false};
54 | };
55 |
56 | } // namespace katran
57 | } // namespace lb
58 |
--------------------------------------------------------------------------------
/katran/lib/MaglevBase.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This program is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License as published by
4 | * the Free Software Foundation; version 2 of the License.
5 | *
6 | * This program is distributed in the hope that it will be useful,
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | * GNU General Public License for more details.
10 | *
11 | * You should have received a copy of the GNU General Public License along
12 | * with this program; if not, write to the Free Software Foundation, Inc.,
13 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14 | */
15 |
16 | #pragma once
17 |
18 | #include
19 | #include
20 |
21 | #include "katran/lib/CHHelpers.h"
22 |
23 | namespace katran {
24 |
25 | /**
26 | * MaglevBase class implements Maglev's permutation and should be used as a base
27 | * class for all versions of Maglev's hashing (more info:
28 | * http://research.google.com/pubs/pub44824.html ; section 3.4)
29 | */
30 | class MaglevBase : public ConsistentHash {
31 | public:
32 | MaglevBase() {}
33 | /**
34 | * @param vector& container for generated permutations
35 | * @param Endpoint& endpoint endpoint for which permutation is going to be
36 | * generated
37 | * @param uint32_t pos position of specified endpoint
38 | * @param uint32_t ring_size size of the hash ring
39 | *
40 | * helper function which will generate Maglev's permutation array for
41 | * specified endpoint on specified possition
42 | */
43 | static void genMaglevPermutation(
44 | std::vector& permutation,
45 | const Endpoint& endpoint,
46 | const uint32_t pos,
47 | const uint32_t ring_size);
48 | };
49 |
50 | } // namespace katran
51 |
--------------------------------------------------------------------------------
/tools/start_katran/build_start_katran.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Copyright (C) 2018-present, Facebook, Inc.
3 | #
4 | # This program is free software; you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation; version 2 of the License.
7 | #
8 | # This program is distributed in the hope that it will be useful,
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | # GNU General Public License for more details.
12 | #
13 | # You should have received a copy of the GNU General Public License along
14 | # with this program; if not, write to the Free Software Foundation, Inc.,
15 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 |
17 | set -xeo pipefail
18 |
19 | create_grpc_template () {
20 | rm -rf start_katran/src/start_katran/lb_katran
21 | mkdir -p start_katran/src/start_katran/lb_katran
22 | protoc -I ../../example_grpc/protos/ ../../example_grpc/protos/katran.proto --go_out=plugins=grpc:start_katran/src/start_katran/lb_katran
23 | }
24 |
25 | get_start_katran_deps() {
26 | pushd .
27 | cd start_katran/src/start_katran/main
28 | go get
29 | popd
30 | }
31 |
32 | build_start_katran() {
33 | pushd .
34 | cd start_katran/src/start_katran/main
35 | go build
36 | popd
37 | }
38 |
39 | echo """
40 | Please make sure that go and grpc dependencies are installed
41 | (
42 | follow instructions @ https://grpc.io/docs/tutorials/basic/go.html
43 | but TL;DR
44 | go get -u google.golang.org/grpc
45 | go get -u github.com/golang/protobuf/protoc-gen-go
46 | )
47 | This script will fail if go is not present
48 | """
49 |
50 | go version 1>/dev/null
51 | export GOPATH=$(pwd)/start_katran
52 | create_grpc_template
53 | get_start_katran_deps
54 | build_start_katran
55 |
--------------------------------------------------------------------------------
/example_grpc/GrpcSignalHandler.cpp:
--------------------------------------------------------------------------------
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 "GrpcSignalHandler.h"
18 |
19 | #include
20 |
21 | namespace lb {
22 | namespace katran {
23 |
24 | GrpcSignalHandler::GrpcSignalHandler(
25 | std::shared_ptr evb,
26 | grpc::Server* server,
27 | int32_t delay)
28 | : folly::AsyncSignalHandler(evb.get()), delay_(delay) {
29 | server_ = server;
30 | evb_ = evb;
31 | };
32 |
33 | void GrpcSignalHandler::signalReceived(int signum) noexcept {
34 | if (shutdownScheduled_) {
35 | LOG(INFO) << "Ignoring signal: " << signum << " as we already scheduled"
36 | << " sighandler to run.";
37 | return;
38 | };
39 | LOG(INFO) << "Signal: " << signum << ", stopping service in " << delay_
40 | << " milliseconds.";
41 | evb_->runInEventBaseThread([this]() {
42 | evb_->runAfterDelay(
43 | [this]() {
44 | LOG(INFO) << "Stopping Katran!";
45 | server_->Shutdown();
46 | },
47 | delay_);
48 | });
49 | shutdownScheduled_ = true;
50 | };
51 | } // namespace katran
52 | } // namespace lb
53 |
--------------------------------------------------------------------------------
/katran/lib/MacHelpers.cpp:
--------------------------------------------------------------------------------
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 "katran/lib/MacHelpers.h"
18 |
19 | #include
20 |
21 | #include
22 |
23 | namespace katran {
24 |
25 | std::vector convertMacToUint(const std::string& macAddress) {
26 | std::vector mac(6);
27 |
28 | folly::MacAddress default_mac;
29 | try {
30 | default_mac.parse(macAddress);
31 | } catch (const std::exception& e) {
32 | LOG(ERROR) << "Exception: " << e.what() << std::endl;
33 | return mac;
34 | }
35 |
36 | auto mac_bytes = default_mac.bytes();
37 | for (int i = 0; i < 6; i++) {
38 | mac[i] = mac_bytes[i];
39 | }
40 | return mac;
41 | }
42 |
43 | std::string convertMacToString(std::vector mac) {
44 | if (mac.size() != 6) {
45 | return "unknown";
46 | }
47 | uint16_t mac_part;
48 | std::string mac_part_string;
49 | std::string mac_string;
50 | for (auto m : mac) {
51 | mac_part = m;
52 | mac_part_string = fmt::format("{0:02x}:", mac_part);
53 | mac_string += mac_part_string;
54 | }
55 | return mac_string;
56 | }
57 |
58 | } // namespace katran
59 |
--------------------------------------------------------------------------------
/katran/decap/bpf/decap_maps.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2019-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 | #ifndef __DECAP_MAPS_H
18 | #define __DECAP_MAPS_H
19 |
20 | /*
21 | * This file contains definition of all maps which has been used by balancer
22 | */
23 |
24 | #include "katran/lib/linux_includes/bpf.h"
25 | #include "katran/lib/linux_includes/bpf_helpers.h"
26 |
27 | #include "katran/lib/bpf/balancer_consts.h"
28 |
29 | #ifndef DECAP_STATS_MAP_SIZE
30 | #define DECAP_STATS_MAP_SIZE 1
31 | #endif
32 |
33 | struct decap_stats {
34 | __u64 decap_v4;
35 | __u64 decap_v6;
36 | __u64 total;
37 | __u64 tpr_misrouted;
38 | __u64 tpr_total;
39 | };
40 |
41 | // map w/ per vip statistics
42 | struct {
43 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
44 | __type(key, __u32);
45 | __type(value, struct decap_stats);
46 | __uint(max_entries, DECAP_STATS_MAP_SIZE);
47 | __uint(map_flags, NO_FLAGS);
48 | } decap_counters SEC(".maps");
49 |
50 | // map, which contains server_id info
51 | struct {
52 | __uint(type, BPF_MAP_TYPE_ARRAY);
53 | __type(key, __u32);
54 | __type(value, __u32);
55 | __uint(max_entries, 1);
56 | __uint(map_flags, NO_FLAGS);
57 | } tpr_server_id SEC(".maps");
58 |
59 | #endif // of _DECAP_MAPS
60 |
--------------------------------------------------------------------------------
/katran/lib/IpHelpers.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include
21 |
22 | namespace katran {
23 |
24 | /**
25 | * struct, which represent given ip address in
26 | * big endian uint32_t ([4]) format for v4(v6)
27 | */
28 | struct beaddr {
29 | union {
30 | uint32_t daddr;
31 | uint32_t v6daddr[4];
32 | };
33 | uint8_t flags;
34 | };
35 |
36 | class IpHelpers {
37 | public:
38 | /**
39 | * @param const string addr address to translate
40 | * @return struct beaddr representation of given address
41 | *
42 | * helper function to translate addr to it's be representation if format
43 | * of beaddr structure. this function could throw, if given string is not
44 | * an ip address.
45 | */
46 | static struct beaddr parseAddrToBe(
47 | const std::string& addr,
48 | bool bigendian = true);
49 | static struct beaddr parseAddrToInt(const std::string& addr);
50 |
51 | static struct beaddr parseAddrToBe(
52 | const folly::IPAddress& addr,
53 | bool bigendian = true);
54 | static struct beaddr parseAddrToInt(const folly::IPAddress& addr);
55 | };
56 |
57 | } // namespace katran
58 |
--------------------------------------------------------------------------------
/katran/lib/MonitoringStructs.h:
--------------------------------------------------------------------------------
1 | // Copyright 2004-present Facebook. All Rights Reserved.
2 |
3 | #pragma once
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | namespace katran {
11 | namespace monitoring {
12 |
13 | constexpr auto kDefaultClientLimit = 10;
14 |
15 | // This is the internal enum for event id. Protocol specific types will need to
16 | // be casted to/from this type. One can take advantage of the UNKNOWN event id
17 | // for handling casting exception.
18 | enum class EventId : uint8_t {
19 | TCP_NONSYN_LRUMISS = 0,
20 | PACKET_TOOBIG = 1,
21 | QUIC_PACKET_DROP_NO_REAL = 2,
22 | UNKNOWN = 255,
23 | };
24 |
25 | // A set of all valid events
26 | extern std::set kAllEventIds;
27 |
28 | // Enum of response status
29 | enum ResponseStatus {
30 | OK = 0,
31 | NOT_SUPPORTED = 1,
32 | TOOMANY_CLIENTS = 2,
33 | INTERNAL_ERROR = 3,
34 | };
35 |
36 | // Helper function converting event to string
37 | std::string toString(const EventId& eventId);
38 |
39 | // Helper operator definition that makes logging easier
40 | std::ostream& operator<<(std::ostream& os, const EventId& eventId);
41 |
42 | struct Event {
43 | EventId id;
44 | uint32_t pktsize;
45 | std::string data;
46 | };
47 |
48 | using ClientId = uint32_t;
49 | using EventIds = std::set;
50 |
51 | /**
52 | * A helper class to store both subscribed events and publisher
53 | */
54 | class ClientSubscriptionIf {
55 | public:
56 | virtual ~ClientSubscriptionIf() = default;
57 | /**
58 | * Stream event to client.
59 | */
60 | virtual void sendEvent(const Event& event) = 0;
61 |
62 | /**
63 | * Return true if this subscription contains the event
64 | */
65 | virtual bool hasEvent(const EventId& event_id) = 0;
66 | };
67 |
68 | using ClientSubscriptionMap =
69 | std::unordered_map>;
70 |
71 | } // namespace monitoring
72 | } // namespace katran
73 |
--------------------------------------------------------------------------------
/katran/tpr/bpf_util/BpfUtil.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #pragma once
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | #include
10 |
11 | namespace katran_tpr::BpfUtil {
12 |
13 | constexpr int kNoFlags = 0;
14 |
15 | SystemMaybe init() noexcept;
16 |
17 | SystemMaybe setRLimit() noexcept;
18 |
19 | int getDirFd(const std::string& path) noexcept;
20 |
21 | SystemMaybe attachCgroupProg(
22 | int progFd,
23 | const std::string& cgroup,
24 | unsigned int flags) noexcept;
25 |
26 | SystemMaybe detachCgroupProg(
27 | int progFd,
28 | const std::string& cgroup) noexcept;
29 |
30 | template
31 | SystemMaybe
32 | updateMapElement(int mapFd, const K& key, const V& value) noexcept {
33 | if (mapFd < 0) {
34 | return SYSTEM_ERROR(EINVAL, fmt::format("Invalid map-fd given: {}", mapFd));
35 | }
36 | if (::bpf_map_update_elem(mapFd, &key, &value, kNoFlags)) {
37 | int savedErrno = errno;
38 | return SYSTEM_ERROR(
39 | savedErrno,
40 | fmt::format(
41 | "Error while updating map: {}, error: {}",
42 | mapFd,
43 | folly::errnoStr(savedErrno)));
44 | }
45 | return noSystemError();
46 | }
47 |
48 | template
49 | SystemMaybe
50 | lookupMapElement(int mapFd, const K& key, V& value) noexcept {
51 | if (mapFd < 0) {
52 | return SYSTEM_ERROR(EINVAL, fmt::format("Invalid map-fd given: {}", mapFd));
53 | }
54 | if (::bpf_map_lookup_elem(mapFd, &key, &value)) {
55 | int savedErrno = errno;
56 | return SYSTEM_ERROR(
57 | savedErrno,
58 | fmt::format(
59 | "Error while looking up in bpf map: {}, error: {}",
60 | mapFd,
61 | folly::errnoStr(savedErrno)));
62 | }
63 | return noSystemError();
64 | }
65 |
66 | } // namespace katran_tpr::BpfUtil
67 |
--------------------------------------------------------------------------------
/katran/lib/PcapMsgMeta.cpp:
--------------------------------------------------------------------------------
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 | #include "katran/lib/PcapMsgMeta.h"
17 | #include
18 |
19 | namespace katran {
20 |
21 | using EventId = monitoring::EventId;
22 |
23 | PcapMsgMeta::PcapMsgMeta(PcapMsg&& msg, uint32_t event)
24 | : msg_(std::move(msg)), event_(event) {}
25 |
26 | PcapMsgMeta::PcapMsgMeta(PcapMsgMeta&& msg) noexcept
27 | : msg_(std::move(msg.msg_)),
28 | event_(msg.event_),
29 | packetLimit_(msg.packetLimit_),
30 | restart_(msg.restart_),
31 | control_(msg.control_),
32 | stop_(msg.stop_),
33 | shutdown_(msg.shutdown_) {}
34 |
35 | PcapMsgMeta& PcapMsgMeta::operator=(PcapMsgMeta&& msg) noexcept {
36 | msg_ = std::move(msg.msg_);
37 | event_ = msg.event_;
38 | packetLimit_ = msg.packetLimit_;
39 | restart_ = msg.restart_;
40 | control_ = msg.control_;
41 | stop_ = msg.stop_;
42 | shutdown_ = msg.shutdown_;
43 | return *this;
44 | }
45 |
46 | PcapMsg& PcapMsgMeta::getPcapMsg() {
47 | return msg_;
48 | }
49 |
50 | EventId PcapMsgMeta::getEventId() {
51 | try {
52 | return static_cast(event_);
53 | } catch (const std::exception& e) {
54 | LOG(ERROR) << fmt::format("invalid event {}: {}", event_, e.what());
55 | return EventId::UNKNOWN;
56 | }
57 | }
58 |
59 | } // namespace katran
60 |
--------------------------------------------------------------------------------
/katran/lib/bpf/healthchecking_consts.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
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 | #ifndef __HEALTHCHECKING_CONSTS_H
18 | #define __HEALTHCHECKING_CONSTS_H
19 |
20 | #define CTRL_MAP_SIZE 4
21 | // position of ifindex of main interface inside hc ctrl array
22 | #define HC_MAIN_INTF_POSITION 3
23 |
24 | #define REDIRECT_EGRESS 0
25 | #define DEFAULT_TTL 64
26 |
27 | // Specify max packet size to avoid packets exceed mss (after encapsulation)
28 | // when set to 0, the healthchecker_kern would not perform skb length check,
29 | // relying on GSO to segment packets exceeding MSS on transmit path
30 | #ifndef HC_MAX_PACKET_SIZE
31 | #define HC_MAX_PACKET_SIZE 0
32 | #endif
33 |
34 | // position in stats map where we are storing generic counters.
35 | #define GENERIC_STATS_INDEX 0
36 |
37 | // code to indicate that packet should be futher processed by pipeline
38 | #define HC_FURTHER_PROCESSING -2
39 |
40 | // size of stats map.
41 | #define STATS_SIZE 1
42 |
43 | #define NO_FLAGS 0
44 |
45 | // for ip-in-ip encap
46 | // source address of the healthcheck would be crafted the same way as data
47 | // packet
48 | // #define MANGLE_HC_SRC 1
49 | #define MANGLED_HC_SRC_PORT 31337
50 |
51 | #define V6DADDR (1 << 0)
52 |
53 | #define HC_SRC_MAC_POS 0
54 | #define HC_DST_MAC_POS 1
55 |
56 | #endif // of __HEALTHCHECKING_CONSTS_H
57 |
--------------------------------------------------------------------------------
/katran/lib/bpf/xdp_pktcntr.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
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "bpf.h"
26 | #include "bpf_helpers.h"
27 |
28 | #define CTRL_ARRAY_SIZE 2
29 | #define CNTRS_ARRAY_SIZE 512
30 |
31 | struct {
32 | __uint(type, BPF_MAP_TYPE_ARRAY);
33 | __type(key, __u32);
34 | __type(value, __u32);
35 | __uint(max_entries, CTRL_ARRAY_SIZE);
36 | } ctl_array SEC(".maps");
37 |
38 | struct {
39 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
40 | __type(key, __u32);
41 | __type(value, __u64);
42 | __uint(max_entries, CNTRS_ARRAY_SIZE);
43 | } cntrs_array SEC(".maps");
44 |
45 | SEC("xdp")
46 | int pktcntr(struct xdp_md* ctx) {
47 | void* data_end = (void*)(long)ctx->data_end;
48 | void* data = (void*)(long)ctx->data;
49 | __u32 ctl_flag_pos = 0;
50 | __u32 cntr_pos = 0;
51 | __u32* flag = bpf_map_lookup_elem(&ctl_array, &ctl_flag_pos);
52 |
53 | if (!flag || (*flag == 0)) {
54 | return XDP_PASS;
55 | };
56 |
57 | __u64* cntr_val = bpf_map_lookup_elem(&cntrs_array, &cntr_pos);
58 | if (cntr_val) {
59 | *cntr_val += 1;
60 | };
61 | return XDP_PASS;
62 | }
63 |
64 | char _license[] SEC("license") = "GPL";
65 |
--------------------------------------------------------------------------------
/tools/start_katran/start_katran/src/start_katran/katranc/katranc.go:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2019-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 | package katranc
18 |
19 | import (
20 | "log"
21 | "start_katran/lb_katran"
22 |
23 | "golang.org/x/net/context"
24 | "google.golang.org/grpc"
25 | )
26 |
27 | func checkError(err error) {
28 | if err != nil {
29 | log.Fatal("Error: ", err)
30 | }
31 | }
32 |
33 | type KatranClient struct {
34 | client lb_katran.KatranServiceClient
35 | }
36 |
37 | func (kc *KatranClient) Init() {
38 | var opts []grpc.DialOption
39 | opts = append(opts, grpc.WithInsecure())
40 | conn, err := grpc.Dial("127.0.0.1:50051", opts...)
41 | if err != nil {
42 | log.Fatalf("Can't connect to local katran server! err is %v\n", err)
43 | }
44 | kc.client = lb_katran.NewKatranServiceClient(conn)
45 | }
46 |
47 | func (kc *KatranClient) ChangeMac(mac string) {
48 | newMac := lb_katran.Mac{Mac: mac}
49 | res, err := kc.client.ChangeMac(context.Background(), &newMac)
50 | checkError(err)
51 | if res.Success {
52 | log.Print("Mac address changed!")
53 | } else {
54 | log.Print("Mac was not changed")
55 | }
56 | }
57 |
58 | func (kc *KatranClient) GetMac() bool {
59 | mac, err := kc.client.GetMac(context.Background(), &lb_katran.Empty{})
60 | if err != nil {
61 | return false
62 | }
63 | log.Printf("Mac address is %v\n", mac.GetMac())
64 | return true
65 | }
66 |
--------------------------------------------------------------------------------
/katran/lib/bpf/introspection.h:
--------------------------------------------------------------------------------
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 | // if KATRAN_INTROSPECTION is enabled
18 | #define MAX_EVENT_SIZE 128
19 |
20 | // introspection events, they are defined regardless because they are used in
21 | // constants which does not depend on the introspection flag
22 | #define TCP_NONSYN_LRUMISS 0
23 | #define PACKET_TOOBIG 1
24 | #define QUIC_PACKET_DROP_NO_REAL 2
25 |
26 | #ifdef KATRAN_INTROSPECTION
27 | // Introspection enabled, enable helpers
28 | #define REPORT_EVENT(xdp, event, data, size, meta_only) \
29 | ({ submit_event((xdp), &event_pipe, (event), data, size, meta_only); })
30 | #define REPORT_TCP_NONSYN_LRUMISS(xdp, data, size, meta_only) \
31 | REPORT_EVENT(xdp, TCP_NONSYN_LRUMISS, data, size, meta_only)
32 | #define REPORT_PACKET_TOOBIG(xdp, data, size, meta_only) \
33 | REPORT_EVENT(xdp, PACKET_TOOBIG, data, size, meta_only)
34 | #define REPORT_QUIC_PACKET_DROP_NO_REAL(xdp, data, size, meta_only) \
35 | REPORT_EVENT(xdp, QUIC_PACKET_DROP_NO_REAL, data, size, meta_only)
36 | #else
37 | // Introspection disabled, define helpers to be noop
38 | #define REPORT_TCP_NONSYN_LRUMISS(...) \
39 | { \
40 | }
41 | #define REPORT_PACKET_TOOBIG(...) \
42 | { \
43 | }
44 | #define REPORT_QUIC_PACKET_DROP_NO_REAL(...) \
45 | { \
46 | }
47 | #endif
48 |
--------------------------------------------------------------------------------
/katran/lib/MurmurHash3.cpp:
--------------------------------------------------------------------------------
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 "MurmurHash3.h"
18 |
19 | namespace katran {
20 |
21 | static inline uint64_t rotl64(uint64_t x, int8_t r) {
22 | return (x << r) | (x >> (64 - r));
23 | }
24 |
25 | uint64_t
26 | MurmurHash3_x64_64(const uint64_t& A, const uint64_t& B, const uint32_t seed) {
27 | uint64_t h1 = seed;
28 | uint64_t h2 = seed;
29 |
30 | uint64_t c1 = 0x87c37b91114253d5llu;
31 | uint64_t c2 = 0x4cf5ad432745937fllu;
32 |
33 | //----------
34 | // body
35 |
36 | uint64_t k1 = A;
37 | uint64_t k2 = B;
38 |
39 | k1 *= c1;
40 | k1 = rotl64(k1, 31);
41 | k1 *= c2;
42 | h1 ^= k1;
43 |
44 | h1 = rotl64(h1, 27);
45 | h1 += h2;
46 | h1 = h1 * 5 + 0x52dce729;
47 |
48 | k2 *= c2;
49 | k2 = rotl64(k2, 33);
50 | k2 *= c1;
51 | h2 ^= k2;
52 |
53 | h2 = rotl64(h2, 31);
54 | h2 += h1;
55 | h2 = h2 * 5 + 0x38495ab5;
56 |
57 | //----------
58 | // finalization
59 |
60 | h1 ^= 16;
61 | h2 ^= 16;
62 |
63 | h1 += h2;
64 | h2 += h1;
65 |
66 | h1 ^= h1 >> 33;
67 | h1 *= 0xff51afd7ed558ccdllu;
68 | h1 ^= h1 >> 33;
69 | h1 *= 0xc4ceb9fe1a85ec53llu;
70 | h1 ^= h1 >> 33;
71 |
72 | h2 ^= h2 >> 33;
73 | h2 *= 0xff51afd7ed558ccdllu;
74 | h2 ^= h2 >> 33;
75 | h2 *= 0xc4ceb9fe1a85ec53llu;
76 | h2 ^= h2 >> 33;
77 |
78 | h1 += h2;
79 |
80 | return h1;
81 | }
82 |
83 | } // namespace katran
84 |
--------------------------------------------------------------------------------
/katran/lib/testing/tools/PacketAttributes.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include
21 | #include "katran/lib/testing/tools/PacketBuilder.h"
22 |
23 | namespace katran {
24 |
25 | struct PacketAttributes {
26 | // Base-64 encoded value of the packet sent to Katran
27 | std::string inputPacket;
28 |
29 | // Human-readable description of the packet being sent
30 | std::string description;
31 |
32 | // Expected return value of the balancer bpf program. Example: "XDP_TX"
33 | std::string expectedReturnValue;
34 |
35 | // Base-64 encoded value of the packet we expect after passing
36 | // the input packet through Katran.
37 | std::string expectedOutputPacket;
38 |
39 | // We set this if we want to verify whether or not the packet was
40 | // routed through global lru
41 | std::optional routedThroughGlobalLru{std::nullopt};
42 |
43 | // Scapy command representation of the input packet for debugging
44 | std::string inputScapyCommand;
45 |
46 | // Scapy command representation of the expected output packet for debugging
47 | std::string expectedOutputScapyCommand;
48 |
49 | // PacketBuilder for input packet
50 | std::optional inputPacketBuilder;
51 |
52 | // PacketBuilder for expected output packet
53 | std::optional expectedOutputPacketBuilder;
54 | };
55 |
56 | } // namespace katran
57 |
--------------------------------------------------------------------------------
/katran/lib/linux_includes/bpf_endian.h:
--------------------------------------------------------------------------------
1 | /* SPDX-License-Identifier: GPL-2.0 */
2 | #ifndef __BPF_ENDIAN__
3 | #define __BPF_ENDIAN__
4 |
5 | #include
6 |
7 | /* LLVM's BPF target selects the endianness of the CPU
8 | * it compiles on, or the user specifies (bpfel/bpfeb),
9 | * respectively. The used __BYTE_ORDER__ is defined by
10 | * the compiler, we cannot rely on __BYTE_ORDER from
11 | * libc headers, since it doesn't reflect the actual
12 | * requested byte order.
13 | *
14 | * Note, LLVM's BPF target has different __builtin_bswapX()
15 | * semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
16 | * in bpfel and bpfeb case, which means below, that we map
17 | * to cpu_to_be16(). We could use it unconditionally in BPF
18 | * case, but better not rely on it, so that this header here
19 | * can be used from application and BPF program side, which
20 | * use different targets.
21 | */
22 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
23 | #define __bpf_ntohs(x) __builtin_bswap16(x)
24 | #define __bpf_htons(x) __builtin_bswap16(x)
25 | #define __bpf_constant_ntohs(x) ___constant_swab16(x)
26 | #define __bpf_constant_htons(x) ___constant_swab16(x)
27 | #define __bpf_ntohl(x) __builtin_bswap32(x)
28 | #define __bpf_htonl(x) __builtin_bswap32(x)
29 | #define __bpf_constant_ntohl(x) ___constant_swab32(x)
30 | #define __bpf_constant_htonl(x) ___constant_swab32(x)
31 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
32 | #define __bpf_ntohs(x) (x)
33 | #define __bpf_htons(x) (x)
34 | #define __bpf_constant_ntohs(x) (x)
35 | #define __bpf_constant_htons(x) (x)
36 | #define __bpf_ntohl(x) (x)
37 | #define __bpf_htonl(x) (x)
38 | #define __bpf_constant_ntohl(x) (x)
39 | #define __bpf_constant_htonl(x) (x)
40 | #else
41 | #error "Fix your compiler's __BYTE_ORDER__?!"
42 | #endif
43 |
44 | #define bpf_htons(x) \
45 | (__builtin_constant_p(x) ? __bpf_constant_htons(x) : __bpf_htons(x))
46 | #define bpf_ntohs(x) \
47 | (__builtin_constant_p(x) ? __bpf_constant_ntohs(x) : __bpf_ntohs(x))
48 | #define bpf_htonl(x) \
49 | (__builtin_constant_p(x) ? __bpf_constant_htonl(x) : __bpf_htonl(x))
50 | #define bpf_ntohl(x) \
51 | (__builtin_constant_p(x) ? __bpf_constant_ntohl(x) : __bpf_ntohl(x))
52 |
53 | #endif /* __BPF_ENDIAN__ */
54 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required (VERSION 3.9 FATAL_ERROR)
2 |
3 | project(
4 | katran
5 | )
6 |
7 | set(CMAKE_MODULE_PATH
8 | "${CMAKE_CURRENT_SOURCE_DIR}/build/fbcode_builder/CMake"
9 | ${CMAKE_MODULE_PATH})
10 |
11 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
12 | # for modules vended by fbcode_builder and getdeps
13 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build/fbcode_builder/CMake)
14 |
15 | # KATRAN_FBCODE_ROOT is where the top level katran/ directory resides, so
16 | # an #include will resolve to
17 | # $KATRAN_FBCODE_ROOT/katran/path/to/file on disk
18 | set(KATRAN_FBCODE_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
19 |
20 | set(KATRAN_INCLUDE_DIR "$")
21 |
22 | set(CMAKE_CXX_STANDARD 17)
23 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
24 | message(STATUS "setting C++ standard to C++${CMAKE_CXX_STANDARD}")
25 |
26 | # for clang's compile_commands.json
27 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
28 |
29 | # Dependencies
30 | find_package(fmt CONFIG REQUIRED)
31 | find_package(folly CONFIG REQUIRED)
32 | find_package(Glog REQUIRED)
33 | find_package(Gflags REQUIRED)
34 | find_package(Threads)
35 | find_package(PkgConfig REQUIRED)
36 | pkg_check_modules(ZSTD REQUIRED libzstd)
37 |
38 | include_directories(".")
39 | add_subdirectory(katran)
40 |
41 | if(BUILD_TESTS)
42 | enable_testing()
43 | include(KatranTest)
44 | endif()
45 |
46 | if(DEFINED ENV{CMAKE_BUILD_EXAMPLE_THRIFT})
47 | message("Building example of thrift and grpc based katran server")
48 | add_subdirectory(example)
49 | endif()
50 |
51 | if(DEFINED ENV{CMAKE_BUILD_EXAMPLE_GRPC})
52 | add_subdirectory(example_grpc)
53 | endif()
54 |
55 | if(DEFINED ENV{CMAKE_BUILD_TOOLS})
56 | add_subdirectory(tools)
57 | endif()
58 |
59 | install(
60 | EXPORT katran-exports
61 | FILE katran-targets.cmake
62 | NAMESPACE katran::
63 | DESTINATION lib/cmake/katran/
64 | )
65 |
66 | include(CMakePackageConfigHelpers)
67 | configure_package_config_file(
68 | cmake/katran-config.cmake.in
69 | ${CMAKE_CURRENT_BINARY_DIR}/katran-config.cmake
70 | INSTALL_DESTINATION lib/cmake/katran/
71 | )
72 |
73 | install(
74 | FILES ${CMAKE_CURRENT_BINARY_DIR}/katran-config.cmake
75 | DESTINATION lib/cmake/katran/
76 | )
77 |
--------------------------------------------------------------------------------
/katran/lib/MaglevHash.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2020-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 "katran/lib/MaglevHash.h"
18 |
19 | namespace katran {
20 |
21 | std::vector MaglevHash::generateHashRing(
22 | std::vector endpoints,
23 | const uint32_t ring_size) {
24 | std::vector result(ring_size, -1);
25 |
26 | if (endpoints.size() == 0) {
27 | return result;
28 | } else if (endpoints.size() == 1) {
29 | for (auto& v : result) {
30 | v = endpoints[0].num;
31 | }
32 | return result;
33 | }
34 |
35 | uint32_t runs = 0;
36 | std::vector permutation(endpoints.size() * 2, 0);
37 | std::vector next(endpoints.size(), 0);
38 |
39 | for (int i = 0; i < endpoints.size(); i++) {
40 | genMaglevPermutation(permutation, endpoints[i], i, ring_size);
41 | }
42 |
43 | for (;;) {
44 | for (int i = 0; i < endpoints.size(); i++) {
45 | auto offset = permutation[2 * i];
46 | auto skip = permutation[2 * i + 1];
47 | // our realization of "weights" for maglev's hash.
48 | for (int j = 0; j < endpoints[i].weight; j++) {
49 | auto cur = (offset + next[i] * skip) % ring_size;
50 | while (result[cur] >= 0) {
51 | next[i] += 1;
52 | cur = (offset + next[i] * skip) % ring_size;
53 | }
54 | result[cur] = endpoints[i].num;
55 | next[i] += 1;
56 | runs++;
57 | if (runs == ring_size) {
58 | return result;
59 | }
60 | }
61 | endpoints[i].weight = 1;
62 | }
63 | }
64 | }
65 |
66 | } // namespace katran
67 |
--------------------------------------------------------------------------------
/tools/tcpdump_encap_helper/README.md:
--------------------------------------------------------------------------------
1 | # tcpdump_encap_helper
2 | this is a simple script which helps to create filters for tcpdump to match on
3 | fields from inner ip packet. currently we can match src/dst/protocol/ports.
4 | by default we are building filter for IPIP encapsulation. -gue flag could be
5 | used to create filters based on GUE encapsulation
6 | ### example of usage.
7 | ```
8 | usage: tcpdump_encap_helper.py [-h] [-m {4,6,46}] [-s SRC] [-d DST] [-p PROTO]
9 | [--sport SPORT] [--dport DPORT]
10 |
11 | this is a tool which helps to create a filter to match fields from internal
12 | header of IPIP/GUE packet
13 |
14 | optional arguments:
15 | -h, --help show this help message and exit
16 | -m {4,6,46}, --mode {4,6,46}
17 | mode of the filter. possible values: 4 (for ipip) 6
18 | (for ip6ip6), 46 (for ip4ip6)
19 | -s SRC, --src SRC src ip address of internal packet. could be ipv4 or
20 | ipv6
21 | -d DST, --dst DST dst ip address of internal packet. could be ipv4 or
22 | ipv6
23 | -p PROTO, --proto PROTO
24 | protocol of internal packet. must be a number. e.g. 6
25 | for tcp or 17 for udp
26 | --sport SPORT src port of internal packet (e.g. if it's udp or tcp)
27 | --dport DPORT dst port of internal packet (e.g. if it's udp or tcp)
28 | ```
29 | as output you will have a filter for tcpdump command
30 |
31 | #### example 1
32 | create a filter to match inner packet w/ dst 10.0.0.1 TCP and destination
33 | port 22. for ipv4inipv6 encapsulation:
34 |
35 | ```
36 | ./tcpdump_encap_helper.py -m 4 -d 10.0.0.1 -p 6 --dport 22
37 | "((ip[36:4] == 0x0A000001 ) and (ip[29:1] == 6 ) and (ip[42:2] == 22 ))"
38 | ```
39 |
40 | no you can use this filter w/ tcpdump. e.g.
41 | ```
42 | tcpdump -ni eth0 "((ip[36:4] == 0x0A000001 ) and (ip[29:1] == 6 ) and (ip[42:2] == 22 ))"
43 | ```
44 |
45 | ### example 2
46 | create a filter to match inner packet w/ dst fc00::1 UDP and source port 10000
47 |
48 | ```
49 | ./tcpdump_encap_helper.py -m 6 -d fc00::1 -p 17 --sport 10000
50 | "((ip6[64:4] == 0xFC000000 ) and (ip6[68:4] == 0x0000 ) and (ip6[72:4] == 0x0000 ) and (ip6[76:4] == 0x0001 ) and (ip6[46:1] == 17 ) and (ip6[80:2] == 10000 ))"
51 | ```
52 |
--------------------------------------------------------------------------------
/tools/xdpdump/XdpEventLogger.cpp:
--------------------------------------------------------------------------------
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 "tools/xdpdump/XdpEventLogger.h"
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | namespace xdpdump {
24 |
25 | namespace {
26 |
27 | constexpr uint8_t kIPv6AddrSize = 16;
28 | }
29 |
30 | std::string XdpEventLogger::binaryToV6String(uint8_t const* v6) {
31 | folly::ByteRange bytes(v6, kIPv6AddrSize);
32 | return folly::IPAddressV6::fromBinary(bytes).str();
33 | }
34 |
35 | std::string XdpEventLogger::longToV4String(uint32_t v4) {
36 | return folly::IPAddressV4::fromLong(v4).str();
37 | }
38 |
39 | XdpEventInfo ProgLogger::handlePerfEvent(const char* data) {
40 | auto msg = reinterpret_cast(data);
41 | XdpEventInfo info;
42 | info.pkt_size = msg->pkt_size;
43 | info.data_len = msg->data_len;
44 | info.hdr_size = sizeof(struct XdpDumpOutput);
45 | if (!mute_) {
46 | log(msg);
47 | }
48 | return info;
49 | }
50 |
51 | void ProgLogger::log(const XdpDumpOutput* msg) {
52 | if (msg->ipv6) {
53 | out_ << "srcv6: " << binaryToV6String((uint8_t*)&msg->srcv6)
54 | << " dstv6: " << binaryToV6String((uint8_t*)&msg->dstv6) << std::endl;
55 | } else {
56 | out_ << "src: " << longToV4String(msg->src)
57 | << " dst: " << longToV4String(msg->dst) << std::endl;
58 | }
59 | out_ << "proto: " << (uint16_t)msg->proto << " sport: " << ntohs(msg->sport)
60 | << " dport: " << ntohs(msg->dport) << " pkt size: " << msg->pkt_size
61 | << " chunk size: " << msg->data_len << std::endl;
62 | }
63 |
64 | } // namespace xdpdump
65 |
--------------------------------------------------------------------------------
/katran/decap/XdpDecapStructs.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 |
21 | namespace katran {
22 |
23 | namespace {
24 | std::string kDefaultMapPath;
25 | const int kDefaultProgPos = 8;
26 | std::string kDefaultInterface = "lo";
27 | } // namespace
28 |
29 | /**
30 | * structure which contains main statistics about XDP based decapsulation
31 | * @param uint64_t decap_v4 number of decapsulated ipip packets
32 | * @param uint64_t decap_v6 number of decapsulated ip(4|6)ip6 packets
33 | * @param uint64_t total total number of packets which was processed
34 | */
35 | struct decap_stats {
36 | uint64_t decap_v4;
37 | uint64_t decap_v6;
38 | uint64_t total;
39 | uint64_t tpr_misrouted;
40 | uint64_t tpr_total;
41 | };
42 |
43 | struct vip_decap_stats {
44 | uint64_t tcp_v4_packets;
45 | uint64_t tcp_v6_packets;
46 | uint64_t udp_v4_packets;
47 | uint64_t udp_v6_packets;
48 | };
49 |
50 | /**
51 | * @param string progPath path to bpf object file w/ xdpdecap program
52 | * @param string mapPath in shared mode - path to bpf prog array
53 | * @param int progPos in shared mode - position in prog array
54 | * @param string interface in standalone mode - interface to attach
55 | * @param bool detachOnExit - should we remove xdp prog from kernel on exit
56 | *
57 | * structure which contains main XdpDecap configuration
58 | */
59 | struct XdpDecapConfig {
60 | std::string progPath;
61 | std::string mapPath = kDefaultMapPath;
62 | int progPos = kDefaultProgPos;
63 | std::string interface = kDefaultInterface;
64 | bool detachOnExit = true;
65 | };
66 |
67 | } // namespace katran
68 |
--------------------------------------------------------------------------------
/katran/lib/IpHelpers.cpp:
--------------------------------------------------------------------------------
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 "IpHelpers.h"
18 |
19 | #include
20 |
21 | namespace katran {
22 |
23 | constexpr int Uint32_bytes = 4;
24 | constexpr uint8_t V6DADDR = 1;
25 |
26 | struct beaddr IpHelpers::parseAddrToBe(
27 | const std::string& addr,
28 | bool bigendian) {
29 | return parseAddrToBe(folly::IPAddress(addr), bigendian);
30 | }
31 |
32 | struct beaddr IpHelpers::parseAddrToBe(
33 | const folly::IPAddress& addr,
34 | bool bigendian) {
35 | struct beaddr translated_addr = {};
36 | if (addr.isV4()) {
37 | translated_addr.flags = 0;
38 | if (bigendian) {
39 | translated_addr.daddr = addr.asV4().toLong();
40 | } else {
41 | translated_addr.daddr = addr.asV4().toLongHBO();
42 | }
43 | } else {
44 | for (int partition = 0; partition < 4; partition++) {
45 | // bytes() return a ptr to char* array
46 | // so we are doing some ptr arithmetics here
47 | uint32_t addr_part =
48 | *(uint32_t*)(addr.bytes() + Uint32_bytes * partition);
49 | if (bigendian) {
50 | translated_addr.v6daddr[partition] = addr_part;
51 | } else {
52 | translated_addr.v6daddr[partition] = folly::Endian::big(addr_part);
53 | }
54 | }
55 | translated_addr.flags = V6DADDR;
56 | }
57 | return translated_addr;
58 | }
59 |
60 | struct beaddr IpHelpers::parseAddrToInt(const std::string& addr) {
61 | return parseAddrToBe(addr, false);
62 | }
63 |
64 | struct beaddr IpHelpers::parseAddrToInt(const folly::IPAddress& addr) {
65 | return parseAddrToBe(addr, false);
66 | }
67 |
68 | } // namespace katran
69 |
--------------------------------------------------------------------------------
/katran/lib/CHHelpers.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | namespace katran {
24 |
25 | constexpr uint32_t kDefaultChRingSize = 65537;
26 |
27 | /**
28 | * struct which describes backend, each backend would have unique number,
29 | * weight (the measurment of how often we would see this endpoint
30 | * on CH ring) and hash value, which will be used as a seed value
31 | * (it should be unique value per endpoint for CH to work as expected)
32 | */
33 | struct Endpoint {
34 | uint32_t num;
35 | uint32_t weight;
36 | uint64_t hash;
37 | };
38 |
39 | /**
40 | * ConsistentHash implements interface, which is used by CHFactory class to
41 | * generate hash ring
42 | */
43 | class ConsistentHash {
44 | public:
45 | /**
46 | * @param std::vector& endpoints, which will be used for CH
47 | * @param uint32_t ring_size size of the CH ring
48 | * @return std::vector vector, which describe CH ring.
49 | */
50 | virtual std::vector generateHashRing(
51 | std::vector endpoints,
52 | const uint32_t ring_size = kDefaultChRingSize) = 0;
53 |
54 | virtual ~ConsistentHash() = default;
55 | };
56 |
57 | enum class HashFunction {
58 | Maglev,
59 | MaglevV2,
60 | };
61 |
62 | /**
63 | * This class implements generic helpers to build Consistent hash rings for
64 | * specified Endpoints.
65 | */
66 | class CHFactory {
67 | public:
68 | /**
69 | * @param HashFunction func to use for hash ring generation
70 | */
71 | static std::unique_ptr make(HashFunction func);
72 | };
73 |
74 | } // namespace katran
75 |
--------------------------------------------------------------------------------
/katran/lib/PcapMsgMeta.h:
--------------------------------------------------------------------------------
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 | #pragma once
17 | #include "katran/lib/MonitoringStructs.h"
18 | #include "katran/lib/PcapMsg.h"
19 |
20 | namespace katran {
21 |
22 | /**
23 | * PcapMsg with additional metadata
24 | */
25 | class PcapMsgMeta {
26 | public:
27 | PcapMsgMeta() {}
28 |
29 | PcapMsgMeta(PcapMsg&& msg, uint32_t event);
30 |
31 | PcapMsgMeta(PcapMsgMeta&& msg) noexcept;
32 |
33 | PcapMsgMeta(const PcapMsgMeta& msg) = delete;
34 |
35 | ~PcapMsgMeta() {}
36 |
37 | PcapMsgMeta& operator=(PcapMsgMeta&& msg) noexcept;
38 |
39 | PcapMsgMeta& operator=(const PcapMsgMeta& msg) = delete;
40 |
41 | PcapMsg& getPcapMsg();
42 |
43 | bool isControl() {
44 | return control_;
45 | }
46 |
47 | void setControl(bool control) {
48 | control_ = control;
49 | }
50 |
51 | bool isRestart() {
52 | return restart_;
53 | }
54 |
55 | void setRestart(bool restart) {
56 | restart_ = restart;
57 | }
58 |
59 | bool isStop() {
60 | return stop_;
61 | }
62 |
63 | void setStop(bool stop) {
64 | stop_ = stop;
65 | }
66 |
67 | bool isShutdown() {
68 | return shutdown_;
69 | }
70 |
71 | void setShutdown(bool shutdown) {
72 | shutdown_ = shutdown;
73 | }
74 |
75 | uint32_t getLimit() {
76 | return packetLimit_;
77 | }
78 |
79 | void setLimit(uint32_t limit) {
80 | packetLimit_ = limit;
81 | }
82 |
83 | monitoring::EventId getEventId();
84 |
85 | private:
86 | PcapMsg msg_;
87 | uint32_t event_{0};
88 | uint32_t packetLimit_{0};
89 | bool restart_{false};
90 | bool control_{false};
91 | bool stop_{false};
92 | bool shutdown_{false};
93 | };
94 |
95 | } // namespace katran
96 |
--------------------------------------------------------------------------------
/katran/lib/BpfAdapter.cpp:
--------------------------------------------------------------------------------
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 "BpfAdapter.h"
18 |
19 | namespace katran {
20 |
21 | BpfAdapter::BpfAdapter(bool set_limits, bool enableBatchOpsIfSupported)
22 | : BaseBpfAdapter(set_limits, enableBatchOpsIfSupported), loader_() {}
23 |
24 | int BpfAdapter::loadBpfProg(
25 | const std::string& bpf_prog,
26 | const bpf_prog_type type,
27 | bool use_names) {
28 | setPrintBpfDbgFlag(true);
29 | int res = loader_.loadBpfFile(bpf_prog, type, use_names);
30 | setPrintBpfDbgFlag(false);
31 | return res;
32 | }
33 |
34 | int BpfAdapter::reloadBpfProg(
35 | const std::string& bpf_prog,
36 | const bpf_prog_type type) {
37 | return loader_.reloadBpfFromFile(bpf_prog, type);
38 | }
39 |
40 | int BpfAdapter::loadBpfProg(
41 | const char* buf,
42 | int buf_size,
43 | const bpf_prog_type type,
44 | bool use_names,
45 | const char* objName) {
46 | return loader_.loadBpfFromBuffer(buf, buf_size, type, use_names, objName);
47 | }
48 |
49 | int BpfAdapter::getMapFdByName(const std::string& name) {
50 | return loader_.getMapFdByName(name);
51 | }
52 |
53 | int BpfAdapter::setInnerMapPrototype(const std::string& name, int map_fd) {
54 | return loader_.setInnerMapPrototype(name, map_fd);
55 | }
56 |
57 | int BpfAdapter::getProgFdByName(const std::string& name) {
58 | return loader_.getProgFdByName(name);
59 | }
60 |
61 | bool BpfAdapter::isMapInProg(
62 | const std::string& progName,
63 | const std::string& name) {
64 | return loader_.isMapInProg(progName, name);
65 | }
66 |
67 | int BpfAdapter::updateSharedMap(const std::string& name, int fd) {
68 | return loader_.updateSharedMap(name, fd);
69 | }
70 |
71 | } // namespace katran
72 |
--------------------------------------------------------------------------------
/katran/lib/testing/utils/KatranTestUtil.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 | #include
19 | #include
20 | #include "katran/lib/KatranLb.h"
21 | #include "katran/lib/testing/utils/KatranTestProvision.h"
22 |
23 | namespace katran {
24 | namespace testing {
25 |
26 | bool testSimulator(katran::KatranLb& lb);
27 | KatranTestParam createDefaultTestParam(TestMode testMode);
28 | KatranTestParam createTPRTestParam();
29 | KatranTestParam createUdpStableRtTestParam();
30 | KatranTestParam createXPopDecapTestParam();
31 | KatranTestParam createUdpFlowMigrationTestParam(
32 | const std::vector<::katran::PacketAttributes>& fixture,
33 | uint8_t totalInvalidations);
34 | KatranTestParam createIcmpTooBigTestParam();
35 | void testOptionalLbCounters(katran::KatranLb& lb, KatranTestParam& testParam);
36 | bool testStableRtCounters(katran::KatranLb& lb, KatranTestParam& testParam);
37 | void validateMapSize(
38 | katran::KatranLb& lb,
39 | const std::string& map_name,
40 | int expected_current,
41 | int expected_max);
42 | void preTestOptionalLbCounters(
43 | katran::KatranLb& lb,
44 | const std::string& healthcheckingProg);
45 | void postTestOptionalLbCounters(
46 | katran::KatranLb& lb,
47 | const std::string& healthcheckingProg);
48 | bool testLbCounters(katran::KatranLb& lb, KatranTestParam& testParam);
49 | bool testXPopDecapCounters(katran::KatranLb& lb, KatranTestParam& testParam);
50 | bool testUdpFlowMigrationCounters(
51 | katran::KatranLb& lb,
52 | KatranTestParam& testParam);
53 | bool testIcmpTooBigCounters(katran::KatranLb& lb, KatranTestParam& testParam);
54 | std::string toString(katran::KatranFeatureEnum feature);
55 |
56 | } // namespace testing
57 | } // namespace katran
58 |
--------------------------------------------------------------------------------
/katran/lib/MaglevHashV2.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This program is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License as published by
4 | * the Free Software Foundation; version 2 of the License.
5 | *
6 | * This program is distributed in the hope that it will be useful,
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | * GNU General Public License for more details.
10 | *
11 | * You should have received a copy of the GNU General Public License along
12 | * with this program; if not, write to the Free Software Foundation, Inc.,
13 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14 | */
15 |
16 | #include "katran/lib/MaglevHashV2.h"
17 |
18 | namespace katran {
19 |
20 | std::vector MaglevHashV2::generateHashRing(
21 | std::vector endpoints,
22 | const uint32_t ring_size) {
23 | std::vector result(ring_size, -1);
24 |
25 | if (endpoints.size() == 0) {
26 | return result;
27 | } else if (endpoints.size() == 1) {
28 | for (auto& v : result) {
29 | v = endpoints[0].num;
30 | }
31 | return result;
32 | }
33 |
34 | auto max_weight = 0;
35 | for (const auto& endpoint : endpoints) {
36 | if (endpoint.weight > max_weight) {
37 | max_weight = endpoint.weight;
38 | }
39 | }
40 |
41 | uint32_t runs = 0;
42 | std::vector permutation(endpoints.size() * 2, 0);
43 | std::vector next(endpoints.size(), 0);
44 | std::vector cum_weight(endpoints.size(), 0);
45 |
46 | for (int i = 0; i < endpoints.size(); i++) {
47 | genMaglevPermutation(permutation, endpoints[i], i, ring_size);
48 | }
49 |
50 | for (;;) {
51 | for (int i = 0; i < endpoints.size(); i++) {
52 | cum_weight[i] += endpoints[i].weight;
53 | if (cum_weight[i] >= max_weight) {
54 | cum_weight[i] -= max_weight;
55 | auto offset = permutation[2 * i];
56 | auto skip = permutation[2 * i + 1];
57 | auto cur = (offset + next[i] * skip) % ring_size;
58 | while (result[cur] >= 0) {
59 | next[i] += 1;
60 | cur = (offset + next[i] * skip) % ring_size;
61 | }
62 | result[cur] = endpoints[i].num;
63 | next[i] += 1;
64 | runs++;
65 | if (runs == ring_size) {
66 | return result;
67 | }
68 | }
69 | }
70 | }
71 | }
72 |
73 | } // namespace katran
74 |
--------------------------------------------------------------------------------
/katran/lib/BpfAdapter.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include "BaseBpfAdapter.h"
24 | #include "BpfLoader.h"
25 |
26 | extern "C" {
27 | #include
28 | #include
29 | }
30 |
31 | namespace katran {
32 |
33 | class BpfAdapter : public BaseBpfAdapter {
34 | public:
35 | explicit BpfAdapter(
36 | bool set_limits = true,
37 | bool enableBatchOpsIfSupported = false);
38 |
39 | // BpfAdapter is not thread safe. Discourage unsafe use by disabling copy
40 | // construction/assignment.
41 | BpfAdapter(BpfAdapter const&) = delete;
42 | BpfAdapter& operator=(BpfAdapter const&) = delete;
43 |
44 | int loadBpfProg(
45 | const std::string& bpf_prog,
46 | const bpf_prog_type type = BPF_PROG_TYPE_UNSPEC,
47 | bool use_names = false) override;
48 |
49 | int reloadBpfProg(
50 | const std::string& bpf_prog,
51 | const bpf_prog_type type = BPF_PROG_TYPE_UNSPEC) override;
52 |
53 | int loadBpfProg(
54 | const char* buf,
55 | int buf_size,
56 | const bpf_prog_type type = BPF_PROG_TYPE_UNSPEC,
57 | bool use_names = false,
58 | const char* objName = "buffer") override;
59 |
60 | int getMapFdByName(const std::string& name) override;
61 |
62 | bool isMapInProg(const std::string& progName, const std::string& name)
63 | override;
64 |
65 | int setInnerMapPrototype(const std::string& name, int map_fd) override;
66 |
67 | int getProgFdByName(const std::string& name) override;
68 |
69 | int updateSharedMap(const std::string& name, int fd) override;
70 |
71 | private:
72 | BpfLoader loader_;
73 | };
74 |
75 | } // namespace katran
76 |
--------------------------------------------------------------------------------
/katran/lib/tests/IpHelpersTest.cpp:
--------------------------------------------------------------------------------
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 |
19 | #include "katran/lib/IpHelpers.h"
20 |
21 | namespace katran {
22 |
23 | TEST(IpHelpersTests, testV4ParsingBe) {
24 | auto addr = IpHelpers::parseAddrToBe("1.1.1.2");
25 | // check that flags are cleared
26 | ASSERT_EQ(addr.flags, 0);
27 | ASSERT_EQ(addr.daddr, 33620225);
28 | }
29 |
30 | TEST(IpHelpersTests, testV4ParsingInt) {
31 | auto addr = IpHelpers::parseAddrToInt("1.1.1.2");
32 | // check that flags are cleared
33 | ASSERT_EQ(addr.flags, 0);
34 | ASSERT_EQ(addr.daddr, 16843010);
35 | }
36 |
37 | TEST(IpHelpersTests, testV6ParsingBe) {
38 | auto addr = IpHelpers::parseAddrToBe("2401:db00:f01c:2002:face:0:d:0");
39 | // checking that flags field is equal to 1 (to show that this is ipv6)
40 | ASSERT_EQ(addr.flags, 1);
41 | ASSERT_EQ(addr.v6daddr[0], 14352676);
42 | ASSERT_EQ(addr.v6daddr[1], 35658992);
43 | ASSERT_EQ(addr.v6daddr[2], 52986);
44 | ASSERT_EQ(addr.v6daddr[3], 3328);
45 | }
46 |
47 | TEST(IpHelpersTests, testV6ParsingInt) {
48 | auto addr = IpHelpers::parseAddrToInt("2401:db00:f01c:2002:face:0:d:0");
49 | // checking that flags field is equal to 1 (to show that this is ipv6)
50 | ASSERT_EQ(addr.flags, 1);
51 | ASSERT_EQ(addr.v6daddr[0], 604101376);
52 | ASSERT_EQ(addr.v6daddr[1], 4028375042);
53 | ASSERT_EQ(addr.v6daddr[2], 4207804416);
54 | ASSERT_EQ(addr.v6daddr[3], 851968);
55 | }
56 |
57 | TEST(IpHelpersTests, testIncorrectAddr) {
58 | // we are testing that our parserAddrToBe throws on
59 | // incorrect input
60 | int i = 1;
61 | try {
62 | IpHelpers::parseAddrToBe("wrong address");
63 | i = 2;
64 | } catch (...) {
65 | i = 1;
66 | }
67 | ASSERT_EQ(i, 1);
68 | }
69 |
70 | } // namespace katran
71 |
--------------------------------------------------------------------------------
/tools/xdpdump/XdpEventReader.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 | #include "katran/lib/PerfBufferEventReader.h"
25 |
26 | #include "katran/lib/PcapMsg.h"
27 | #include "katran/lib/PcapWriter.h"
28 | #include "tools/xdpdump/XdpDumpStructs.h"
29 | #include "tools/xdpdump/XdpEventLogger.h"
30 |
31 | namespace xdpdump {
32 |
33 | class XdpEventLogger;
34 |
35 | /**
36 | * Perf event reader implementation. we are reading data
37 | * from XDP, print it to the cli, and, if configured
38 | * sending it to pcapWriter thru MPMCQueue.
39 | */
40 | class XdpEventReader : public katran::PerfBufferEventReader {
41 | public:
42 | /**
43 | * @param shared_ptr> queue to pcapWriter
44 | */
45 | explicit XdpEventReader(
46 | std::shared_ptr> queue,
47 | std::shared_ptr eventLogger)
48 | : queue_(queue), eventLogger_(eventLogger) {}
49 |
50 | /**
51 | * @param int cpu
52 | * @param const char* data received from the XDP prog.
53 | * @param size_t size of the data chunk
54 | */
55 | void handlePerfBufferEvent(int cpu, const char* data, size_t size) noexcept
56 | override;
57 |
58 | private:
59 | /**
60 | * queue where we write data, which will be read by PcapWriter.
61 | * write is non-blocking. so if queue is full - we will drop the packet
62 | */
63 | std::shared_ptr> queue_;
64 |
65 | /**
66 | * counter of how many times non blocking write failed.
67 | */
68 | uint64_t queueFull_;
69 |
70 | std::shared_ptr eventLogger_;
71 | };
72 |
73 | } // namespace xdpdump
74 |
--------------------------------------------------------------------------------
/example_grpc/build_grpc_client.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Copyright (C) 2018-present, Facebook, Inc.
4 | #
5 | # This program 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; version 2 of the License.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License along
15 | # with this program; if not, write to the Free Software Foundation, Inc.,
16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 |
18 | set -xeo pipefail
19 |
20 | create_grpc_template () {
21 | rm -rf goclient/src/katranc/lb_katran
22 | mkdir -p goclient/src/katranc/lb_katran
23 | protoc -I protos katran.proto --go_out=goclient/src/katranc/lb_katran --go_grpc_out=goclient/src/katranc/lb_katran
24 | }
25 |
26 | get_goclient_deps() {
27 | pushd .
28 | cd goclient/src/katranc/main
29 | GO111MODULE=auto go get
30 | popd
31 | }
32 |
33 | build_goclient() {
34 | pushd .
35 | cd goclient/src/katranc/main
36 | GO111MODULE=auto go build
37 | popd
38 | }
39 |
40 | echo """
41 | Please make sure that go and grpc dependencies are installed
42 | (
43 | https://grpc.io/docs/protoc-installation/ for installing protoc
44 | but TL;DR
45 | apt install -y protobuf-compiler
46 | protoc --version # Ensure compiler version is 3+
47 | https://grpc.io/docs/languages/go/quickstart/ for installing grpc
48 | but TL;DR
49 | go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
50 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
51 | export PATH="$PATH:$(go env GOPATH)/bin"
52 | )
53 | This script will fail if go is not present
54 |
55 | IMPORTANT:
56 | If you get the following error:
57 | protoc-gen-go_grpc: program not found or is not executable
58 | Please specify a program using absolute path or make sure the program is available in your PATH system variable
59 |
60 | And ls $(go env GOPATH)/bin/protoc-gen-go-grpc exists please do:
61 | cp $(go env GOPATH)/bin/protoc-gen-go-grpc $(go env GOPATH)/bin/protoc-gen-go_grpc
62 | """
63 | # fail hard if go or protoc is not installed
64 | go version 1>/dev/null
65 | protoc --version 1>/dev/null
66 | # adding export paths
67 | export GOPATH=$(pwd)/goclient
68 | create_grpc_template
69 | get_goclient_deps
70 | build_goclient
71 |
--------------------------------------------------------------------------------
/katran/lib/KatranSimulator.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 | #include "katran/lib/KatranSimulatorUtils.h"
23 |
24 | #include
25 |
26 | namespace katran {
27 |
28 | /**
29 | * KatranSimulator allows end user to simulate what is going to happen
30 | * with specified packet after it is processed by katran load balancer.
31 | * For e.g. where (address of the real) this packet is going to be sent
32 | */
33 | class KatranSimulator final {
34 | public:
35 | /**
36 | * @param int progFd descriptor of katran xdp program
37 | */
38 | explicit KatranSimulator(int progFd);
39 | ~KatranSimulator();
40 |
41 | /**
42 | * @param KatranFlow& flow that we are interested in
43 | * @return string ip address of the real (or empty string if packet will not
44 | * be sent)
45 | *
46 | * getRealForFlow helps to determines where specific flow is going to be sent
47 | * by returning ip address of the real
48 | */
49 | const std::string getRealForFlow(const KatranFlow& flow);
50 |
51 | // runSimulation takes packet (in iobuf represenation) and
52 | // run it through katran bpf program. It returns a modified pckt, if the
53 | // result was XDP_TX or nullptr otherwise.
54 | std::unique_ptr runSimulation(
55 | std::unique_ptr pckt);
56 |
57 | private:
58 | std::unique_ptr runSimulationInternal(
59 | std::unique_ptr pckt);
60 |
61 | // Affinitize simulator evb thread to CPU 0.
62 | // This ensures that subsequent simulations run on the same CPU and hit
63 | // same per-CPU maps.
64 | void affinitizeSimulatorThread();
65 |
66 | int progFd_;
67 | folly::ScopedEventBaseThread simulatorEvb_{"KatranSimulator"};
68 | };
69 | } // namespace katran
70 |
--------------------------------------------------------------------------------
/tools/start_katran/start_katran/src/start_katran/topology_parser/topology_parser.go:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2019-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 | package topology_parser
18 |
19 | import (
20 | "bytes"
21 | "fmt"
22 | "log"
23 | "runtime"
24 | "strconv"
25 | )
26 |
27 | const (
28 | TOPOLOGY_DIR string = "/sys/devices/system/cpu/cpu"
29 | NUMA_NODE_FILE string = "/topology/physical_package_id"
30 | )
31 |
32 | type CpuTopology struct {
33 | Cpu2Numa map[int]int
34 | Numa2Cpu map[int][]int
35 | Ncpus int
36 | }
37 |
38 | func getNumaNodeOfCpu(i int) int {
39 | fileName := TOPOLOGY_DIR + strconv.Itoa(i) + NUMA_NODE_FILE
40 | numa_bytes, err := os.ReadFile(fileName)
41 | if err != nil {
42 | log.Fatal("cannot parse numa node id for file ", i, err)
43 | }
44 | numa_slice := bytes.Split(numa_bytes, []byte{'\n'})
45 | if len(numa_slice) < 1 {
46 | log.Fatal("invalid numa file format ", string(numa_bytes))
47 | }
48 | numa, err := strconv.Atoi(string(numa_slice[0]))
49 | if err != nil {
50 | log.Fatal("cannot converit numa id to int ", err)
51 | }
52 | return numa
53 | }
54 |
55 | func (topo *CpuTopology) GetNumaListForCpus(cpus []int) []int {
56 | var numa_nodes []int
57 | for _, cpu := range cpus {
58 | if node, exists := topo.Cpu2Numa[cpu]; exists {
59 | numa_nodes = append(numa_nodes, node)
60 | } else {
61 | log.Fatal("cant find numa mapping for cpu: ", cpu)
62 | }
63 | }
64 | return numa_nodes
65 | }
66 |
67 | func GetCpuTopology() CpuTopology {
68 | ncpus := runtime.NumCPU()
69 | fmt.Println("number of CPUs ", ncpus)
70 | var topology CpuTopology
71 | topology.Cpu2Numa = make(map[int]int)
72 | topology.Numa2Cpu = make(map[int][]int)
73 | topology.Ncpus = ncpus
74 | for i := 0; i < ncpus; i++ {
75 | numa := getNumaNodeOfCpu(i)
76 | topology.Cpu2Numa[i] = numa
77 | topology.Numa2Cpu[numa] = append(topology.Numa2Cpu[numa], i)
78 | }
79 | return topology
80 | }
81 |
--------------------------------------------------------------------------------
/katran/tpr/bpf_util/BpfSkeleton.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #pragma once
4 |
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | namespace katran_tpr {
11 |
12 | template
13 | class BpfSkeleton {
14 | private:
15 | T* skel_;
16 |
17 | private:
18 | BpfSkeleton() : skel_(nullptr) {}
19 |
20 | public:
21 | ~BpfSkeleton() {
22 | if (skel_) {
23 | T::destroy(skel_);
24 | }
25 | }
26 |
27 | // Make them deleted to keep it simple and safe
28 | BpfSkeleton(const BpfSkeleton&) = delete;
29 | BpfSkeleton& operator=(const BpfSkeleton&) = delete;
30 |
31 | BpfSkeleton(BpfSkeleton&&) = delete;
32 | BpfSkeleton& operator=(BpfSkeleton&&) = delete;
33 |
34 | static BpfSkeleton make() {
35 | return BpfSkeleton();
36 | }
37 |
38 | static folly::ByteRange elfBytes() {
39 | size_t size{0};
40 | auto bytes = static_cast(T::elf_bytes(&size));
41 | folly::ByteRange buffer(bytes, size);
42 |
43 | return buffer;
44 | }
45 |
46 | SystemMaybe open(
47 | const struct bpf_object_open_opts* opts = nullptr) noexcept {
48 | if (skel_) {
49 | return SYSTEM_ERROR(EBUSY, "BpfSkeleton has already been opened");
50 | }
51 |
52 | skel_ = T::open(opts);
53 | if (auto error = libbpf_get_error(skel_)) {
54 | skel_ = nullptr;
55 | return SYSTEM_ERROR(error, "BpfSkeleton open failed");
56 | }
57 |
58 | return noSystemError();
59 | }
60 |
61 | SystemMaybe load() noexcept {
62 | if (skel_) {
63 | if (auto error = T::load(skel_)) {
64 | return SYSTEM_ERROR(error, "BpfSkeleton load failed");
65 | }
66 |
67 | return noSystemError();
68 | } else {
69 | return SYSTEM_ERROR(EINVAL, "BpfSkeleton is invalid");
70 | }
71 | }
72 |
73 | SystemMaybe attach() noexcept {
74 | if (skel_) {
75 | if (auto error = T::attach(skel_)) {
76 | return SYSTEM_ERROR(error, "BpfSkeleton attach failed");
77 | }
78 |
79 | return noSystemError();
80 | } else {
81 | return SYSTEM_ERROR(EINVAL, "BpfSkeleton is invalid");
82 | }
83 | }
84 |
85 | void detach() noexcept {
86 | if (skel_) {
87 | return T::detach(skel_);
88 | }
89 | }
90 |
91 | const T* operator->() const noexcept {
92 | return skel_;
93 | }
94 |
95 | T* operator->() noexcept {
96 | return skel_;
97 | }
98 | };
99 |
100 | } // namespace katran_tpr
101 |
--------------------------------------------------------------------------------
/cmake/KatranTest.cmake:
--------------------------------------------------------------------------------
1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
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 | include(CTest)
17 | if(BUILD_TESTS)
18 | find_library(BOOST_SYSTEM libboost_system.a boost_system)
19 | find_package(FOLLY CONFIG REQUIRED)
20 | find_library(GTEST gtest)
21 | find_path(GTEST_INCLUDE_DIR gtest)
22 | find_library(GMOCK gmock)
23 | find_library(PTHREAD pthread)
24 | include(GoogleTest)
25 | endif()
26 |
27 | function(katran_add_test)
28 | if(NOT BUILD_TESTS)
29 | return()
30 | endif()
31 |
32 | set(options)
33 | set(one_value_args TARGET WORKING_DIRECTORY PREFIX)
34 | set(multi_value_args SOURCES DEPENDS INCLUDES EXTRA_ARGS)
35 | cmake_parse_arguments(PARSE_ARGV 0 KATRAN_TEST "${options}" "${one_value_args}" "${multi_value_args}")
36 |
37 | if(NOT KATRAN_TEST_TARGET)
38 | message(FATAL_ERROR "The TARGET parameter is mandatory.")
39 | endif()
40 |
41 | if(NOT KATRAN_TEST_SOURCES)
42 | set(KATRAN_TEST_SOURCES "${KATRAN_TEST_TARGET}.cpp")
43 | endif()
44 |
45 | add_executable(${KATRAN_TEST_TARGET}
46 | "${KATRAN_TEST_SOURCES}"
47 | # implementation of 'main()' that also calls folly::init
48 | "${KATRAN_FBCODE_ROOT}/katran/lib/tests/common/TestMain.cpp"
49 | )
50 |
51 | target_link_libraries(${KATRAN_TEST_TARGET} PRIVATE
52 | "${KATRAN_TEST_DEPENDS}"
53 | ${GTEST}
54 | )
55 |
56 | target_include_directories(${KATRAN_TEST_TARGET} PRIVATE
57 | ${BPF_INCLUDE_DIRS}
58 | ${GTEST_INCLUDE_DIR}
59 | ${FOLLY_INCLUDE_DIR}
60 | ${KATRAN_INCLUDE_DIR}
61 | ${KATRAN_EXTRA_INCLUDE_DIRECTORIES}
62 | ${KATRAN_TEST_INCLUDES}
63 | )
64 |
65 | gtest_discover_tests("${KATRAN_TEST_TARGET}"
66 | EXTRA_ARGS "${KATRAN_TEST_EXTRA_ARGS}"
67 | WORKING_DIRECTORY "${KATRAN_TEST_WORKING_DIRECTORY}"
68 | TEST_PREFIX ${KATRAN_TEST_PREFIX}
69 | TEST_LIST KATRAN_TEST_CASES)
70 |
71 | set_tests_properties(${KATRAN_TEST_CASES} PROPERTIES TIMEOUT 120)
72 | endfunction()
73 |
--------------------------------------------------------------------------------
/katran/tpr/TPRStatsPoller.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #pragma once
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | namespace katran_tpr {
14 |
15 | /**
16 | * Library class to periodically poll stats exported by the tcp_router_stats
17 | * program. The exported stats are then appended to the fb303-prefix
18 | */
19 | class TPRStatsPoller : public folly::AsyncTimeout {
20 | public:
21 | explicit TPRStatsPoller(
22 | RunningMode mode,
23 | folly::EventBase* evb,
24 | int statsMapFd);
25 |
26 | ~TPRStatsPoller() override;
27 |
28 | void timeoutExpired() noexcept override;
29 |
30 | /**
31 | * Shutdown the Stats Poller. Useful for safe / clean destruction.
32 | */
33 | void shutdown();
34 |
35 | /**
36 | * Start polling for the TPR stats from the bpf program.
37 | */
38 | folly::Expected runStatsPoller();
39 |
40 | /**
41 | * Collects aggregated tcp_router_stats over numCpus.
42 | */
43 | folly::Expected collectTPRStats(
44 | int numCpus);
45 |
46 | /**
47 | * Returns number of cpus in the host.
48 | * (Public for unit tests)
49 | */
50 | static folly::Expected getCpuCount();
51 |
52 | protected:
53 | virtual void incrementCounter(const std::string& name);
54 | virtual void setCounter(const std::string& name, int64_t val);
55 | virtual void setStatsCounters(const tcp_router_stats& stats);
56 |
57 | private:
58 | /**
59 | * helper functiom to periodically update fb303 stats
60 | */
61 | void updateStatsPeriodically();
62 |
63 | protected:
64 | RunningMode mode_;
65 |
66 | private:
67 | /**
68 | * event base to run periodic tasks
69 | */
70 | folly::EventBase* evb_;
71 |
72 | /**
73 | * Optional prefix for the fb303 counter
74 | */
75 | std::string statsPrefix_;
76 |
77 | /**
78 | * FD of the bpf map containing per-cpu stats
79 | */
80 | int statsMapFd_{-1};
81 |
82 | /**
83 | * Number of available cpus in the host. It is used to aggregate per-cpu
84 | * counters in the bpf map.
85 | */
86 | int numCpus_{0};
87 | /** flag to indicate that the server is in the shutdown phase
88 | * this is to make sure that we do not schedule events such as ones to start
89 | * taking traffic if this service moves to the shutdown / draining phase
90 | */
91 | std::atomic shutdown_{false};
92 | };
93 |
94 | } // namespace katran_tpr
95 |
--------------------------------------------------------------------------------
/katran/lib/testing/utils/Base64Helpers.cpp:
--------------------------------------------------------------------------------
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 "katran/lib/testing/utils/Base64Helpers.h"
18 |
19 | #include
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | namespace katran {
28 |
29 | std::string Base64Helpers::base64Encode(folly::IOBuf* buf) {
30 | using namespace boost::archive::iterators;
31 | using b64it = base64_from_binary>;
32 | int output_size = (buf->length() * 8 + 5) / 6;
33 | std::string encoded(output_size, '*');
34 | auto data = new char[buf->length()];
35 | if (data == nullptr) {
36 | // return empty string. as we are using this in tests only that would just
37 | // mean that we have failed a test. log line will show reason why.
38 | LOG(ERROR) << "Memory allocation during base64 encodingf failed";
39 | return "";
40 | }
41 | std::memcpy(data, buf->data(), buf->length());
42 | std::copy(b64it(data), b64it((char*)data + (buf->length())), encoded.begin());
43 | for (int i = 0; i < (3 - (buf->length() % 3)) % 3; i++) {
44 | encoded.push_back('=');
45 | }
46 | delete[] data;
47 | return encoded;
48 | }
49 |
50 | std::string Base64Helpers::base64Decode(std::string encoded) {
51 | using namespace boost::archive::iterators;
52 | using b64it =
53 | transform_width, 8, 6>;
54 |
55 | auto decoded =
56 | std::string(b64it(std::begin(encoded)), b64it(std::end(encoded)));
57 | int padded_chars = 0;
58 | while (true) {
59 | if (encoded[encoded.size() - 1] != '=') {
60 | return decoded.substr(0, decoded.size() - padded_chars);
61 | }
62 | encoded.pop_back();
63 | padded_chars++;
64 | }
65 | }
66 |
67 | } // namespace katran
68 |
--------------------------------------------------------------------------------
/tools/start_katran/start_katran/src/start_katran/start_binary/start_binary.go:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2019-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 | package start_binary
18 |
19 | import (
20 | "bufio"
21 | "fmt"
22 | "io"
23 | "log"
24 | "os/exec"
25 | "start_katran/default_watcher"
26 | "start_katran/katranc"
27 | "strings"
28 | "time"
29 | )
30 |
31 | type StartKatranArgs struct {
32 | BinaryPath string
33 | Args string
34 | }
35 |
36 | func readLog(log io.ReadCloser) {
37 | scanner := bufio.NewScanner(log)
38 | for scanner.Scan() {
39 | fmt.Println(scanner.Text())
40 | }
41 |
42 | }
43 |
44 | const (
45 | MAX_RETRIES int = 60
46 | )
47 |
48 | func StartKatran(kc *katranc.KatranClient, cmd StartKatranArgs) {
49 | default_mac := default_watcher.GetDefaultGatewayMac()
50 | if len(default_mac) == 0 {
51 | log.Fatal("cannot resolve mac address of default gateway")
52 | }
53 | cmd.Args = cmd.Args + " -default_mac=" + default_mac
54 | args := strings.Split(cmd.Args, " ")
55 | start_cmd := exec.Command(cmd.BinaryPath, args...)
56 | stdout, err := start_cmd.StdoutPipe()
57 | if err != nil {
58 | log.Fatal("error while trying to get stdout ", err)
59 | }
60 | stderr, err := start_cmd.StderrPipe()
61 | if err != nil {
62 | log.Fatal("error while trying to get stderr ", err)
63 | }
64 | if err := start_cmd.Start(); err != nil {
65 | log.Fatal("error while trying to start katran ", err)
66 | }
67 | go readLog(stdout)
68 | go readLog(stderr)
69 | kc.Init()
70 | cur_retry := 0
71 | for !kc.GetMac() {
72 | if cur_retry++; cur_retry == MAX_RETRIES {
73 | log.Fatal("Cannot connect to local katran server")
74 | }
75 | log.Printf("cannot reach katran server. retrying in one second\n")
76 | time.Sleep(1 * time.Second)
77 | }
78 | log.Printf("katran is up and running\n")
79 | go default_watcher.CheckDefaultGwMac(kc, default_mac)
80 | if err := start_cmd.Wait(); err != nil {
81 | log.Fatal("error while waiting katran to finish ", err)
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/katran/lib/testing/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | if(NOT BUILD_TESTS)
2 | return()
3 | endif()
4 |
5 | include(KatranTest)
6 |
7 | add_library(base64_helpers STATIC
8 | utils/Base64Helpers.h
9 | utils/Base64Helpers.cpp
10 | )
11 |
12 | target_link_libraries(base64_helpers
13 | "glog::glog"
14 | "${GFLAGS}"
15 | "Folly::folly"
16 | "${BOOST_SYSTEM}"
17 | "katranlb"
18 | )
19 |
20 | target_include_directories(
21 | base64_helpers PUBLIC
22 | "${GTEST_INCLUDE_DIR}"
23 | "${KATRAN_INCLUDE_DIR}"
24 | )
25 |
26 | add_library(pcap_parser STATIC
27 | tools/PcapParser.h
28 | tools/PcapParser.cpp
29 | )
30 |
31 | target_link_libraries(pcap_parser
32 | base64_helpers
33 | pcapwriter
34 | "Folly::folly"
35 | "glog::glog"
36 | "${BOOST_SYSTEM}"
37 | )
38 |
39 | add_library(bpftester STATIC
40 | framework/BpfTester.h
41 | framework/BpfTester.cpp
42 | tools/PacketBuilder.h
43 | tools/PacketBuilder.cpp
44 | fixtures/KatranBaseTestFixtures.h
45 | fixtures/KatranHCTestFixtures.h
46 | fixtures/KatranGueTestFixtures.h
47 | fixtures/KatranTPRTestFixtures.h
48 | fixtures/KatranIcmpTooBigTestFixtures.h
49 | fixtures/KatranLpmSrcLookupTestFixtures.h
50 | fixtures/KatranUdpFlowMigrationTestFixtures.h
51 | )
52 |
53 | target_link_libraries(bpftester
54 | "Folly::folly"
55 | "glog::glog"
56 | pcap_parser
57 | bpfadapter
58 | )
59 |
60 | katran_add_test(TARGET base64helpers-tests
61 | SOURCES
62 | utils/Base64Test.cpp
63 | DEPENDS
64 | base64_helpers
65 | katranlb
66 | ${GTEST}
67 | "glog::glog"
68 | ${GFLAGS}
69 | "Folly::folly"
70 | ${LIBUNWIND}
71 | INCLUDES
72 | base64_helpers
73 | )
74 |
75 | add_library(katran_test_provision STATIC
76 | utils/KatranTestProvision.h
77 | utils/KatranTestProvision.cpp
78 | )
79 |
80 | target_link_libraries(katran_test_provision
81 | katranlb
82 | )
83 |
84 | add_library(katran_test_util STATIC
85 | utils/KatranTestUtil.h
86 | utils/KatranTestUtil.cpp
87 | )
88 |
89 | target_link_libraries(katran_test_util
90 | katran_test_provision
91 | katranlb
92 | bpftester
93 | )
94 |
95 | # katran_tester is a 'standalone' integration test
96 | add_executable(katran_tester framework/katran_tester.cpp)
97 |
98 | target_link_libraries(katran_tester
99 | katranlb
100 | bpftester
101 | katran_test_provision
102 | katran_test_util
103 | ${GFLAGS}
104 | ${GTEST}
105 | )
106 |
107 | target_include_directories(katran_tester PRIVATE
108 | ${BPF_INCLUDE_DIRS}
109 | ${GTEST_INCLUDE_DIR}
110 | ${FOLLY_INCLUDE_DIR}
111 | ${KATRAN_INCLUDE_DIR}
112 | )
113 |
--------------------------------------------------------------------------------
/katran/lib/DataWriter.h:
--------------------------------------------------------------------------------
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 | #pragma once
17 | #include
18 |
19 | namespace katran {
20 |
21 | /**
22 | * class which implements interface, used by PcapWriter to write data, received
23 | * from katran
24 | */
25 |
26 | class DataWriter {
27 | public:
28 | virtual ~DataWriter() {}
29 |
30 | /**
31 | * @param const void *ptr data to write
32 | * @param std::size_t size of the data
33 | *
34 | * called when data needs to be written
35 | */
36 | virtual void writeData(const void* ptr, std::size_t size) = 0;
37 |
38 | /**
39 | * @param const void *ptr header data to write
40 | * @param std::size_t size of the header data
41 | *
42 | * This is helpful for writers that want to take different code path
43 | * for writing headers (e.g. record header)
44 | * For those writers that do not differentiate header from data,
45 | * the default implementation is simply writeData()
46 | */
47 | virtual void writeHeader(const void* ptr, std::size_t size) {
48 | writeData(ptr, size);
49 | }
50 |
51 | /**
52 | * @param amount -- amount of bytes to write.
53 | *
54 | * Check if we're able to write `amount` bytes into storage. Returns true
55 | * if yes.
56 | */
57 | virtual bool available(std::size_t amount) = 0;
58 |
59 | /**
60 | * reset data writer. so if we would start to writeData again - it wont be
61 | * appended to existing one.
62 | */
63 | virtual bool restart() = 0;
64 |
65 | /**
66 | * stop writing data. flush everything which was not yet flushed, into storage
67 | */
68 | virtual bool stop() = 0;
69 |
70 | /**
71 | * @return std::size_t bytes which has been already written
72 | */
73 | std::size_t writtenBytes() {
74 | return writtenBytes_;
75 | }
76 |
77 | protected:
78 | /**
79 | * size_t wryteBytes is used to record amount of bytes that already
80 | * have been written.
81 | */
82 | std::size_t writtenBytes_{0};
83 | };
84 |
85 | } // namespace katran
86 |
--------------------------------------------------------------------------------
/katran/lib/PcapMsg.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 |
21 | #include
22 |
23 | namespace katran {
24 | /**
25 | * Helper class-wrapper for packets, received from forwarding plane
26 | */
27 | class PcapMsg {
28 | public:
29 | PcapMsg();
30 | /**
31 | * @param const char* pckt pointer to the raw packet
32 | * @param uint32_t origLen original length of the packet on wire
33 | * @param uint32_t capturedLen length of the captured segment
34 | */
35 | PcapMsg(const char* pckt, uint32_t origLen, uint32_t capturedLen);
36 | PcapMsg(PcapMsg&& msg) noexcept;
37 | PcapMsg(const PcapMsg& msg) = delete;
38 | ~PcapMsg();
39 | PcapMsg& operator=(PcapMsg&& msg) noexcept;
40 | PcapMsg& operator=(const PcapMsg& msg) = delete;
41 |
42 | uint32_t getOrigLen() {
43 | return origLen_;
44 | }
45 | uint32_t getOrigLen() const {
46 | return origLen_;
47 | }
48 | uint32_t getCapturedLen() {
49 | return capturedLen_;
50 | }
51 | uint32_t getCapturedLen() const {
52 | return capturedLen_;
53 | }
54 | const uint8_t* getRawBuffer() {
55 | return pckt_->data();
56 | }
57 | const uint8_t* getRawBuffer() const {
58 | return pckt_->data();
59 | }
60 |
61 | /**
62 | * PcapMsg with a pointer to the packet equals to nullptr treated as a
63 | * marker message to turn off pcap file writer
64 | */
65 | bool emptyMsg() {
66 | return (pckt_ == nullptr);
67 | }
68 |
69 | uint32_t trim(uint32_t snaplen) {
70 | return capturedLen_ = std::min(capturedLen_, snaplen);
71 | }
72 |
73 | private:
74 | /**
75 | * IOBuf which contains chunk of the captured packet
76 | */
77 | std::unique_ptr pckt_;
78 | /**
79 | * length of original packet
80 | */
81 | uint32_t origLen_{0};
82 | /**
83 | * length of the captured chunk. as we could e.g. capture only first N bytes
84 | * of the packet
85 | */
86 | uint32_t capturedLen_{0};
87 | };
88 |
89 | } // namespace katran
90 |
--------------------------------------------------------------------------------
/katran/lib/bpf/healthchecking_maps.h:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
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 | #ifndef __HEALTHCHECKING_MAPS_H
18 | #define __HEALTHCHECKING_MAPS_H
19 |
20 | #include "katran/lib/linux_includes/bpf.h"
21 | #include "katran/lib/linux_includes/bpf_helpers.h"
22 |
23 | #include "katran/lib/bpf/balancer_consts.h"
24 | #include "katran/lib/bpf/healthchecking_consts.h"
25 | #include "katran/lib/bpf/healthchecking_structs.h"
26 |
27 | struct {
28 | __uint(type, BPF_MAP_TYPE_ARRAY);
29 | __type(key, __u32);
30 | __type(value, __u32);
31 | __uint(max_entries, CTRL_MAP_SIZE);
32 | } hc_ctrl_map SEC(".maps");
33 |
34 | struct {
35 | __uint(type, BPF_MAP_TYPE_HASH);
36 | __type(key, __u32);
37 | __type(value, struct hc_real_definition);
38 | __uint(max_entries, MAX_REALS);
39 | } hc_reals_map SEC(".maps");
40 |
41 | struct {
42 | __uint(type, BPF_MAP_TYPE_ARRAY);
43 | __type(key, __u32);
44 | __type(value, struct hc_real_definition);
45 | __uint(max_entries, 2);
46 | __uint(map_flags, NO_FLAGS);
47 | } hc_pckt_srcs_map SEC(".maps");
48 |
49 | struct {
50 | __uint(type, BPF_MAP_TYPE_ARRAY);
51 | __type(key, __u32);
52 | __type(value, struct hc_mac);
53 | __uint(max_entries, 2);
54 | __uint(map_flags, NO_FLAGS);
55 | } hc_pckt_macs SEC(".maps");
56 |
57 | // map which contains counters for monitoring
58 | struct {
59 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
60 | __type(key, __u32);
61 | __type(value, struct hc_stats);
62 | __uint(max_entries, STATS_SIZE);
63 | __uint(map_flags, NO_FLAGS);
64 | } hc_stats_map SEC(".maps");
65 |
66 | struct {
67 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
68 | __type(key, __u32);
69 | __type(value, __u64);
70 | __uint(max_entries, MAX_VIPS);
71 | __uint(map_flags, NO_FLAGS);
72 | } per_hckey_stats SEC(".maps");
73 |
74 | struct {
75 | __uint(type, BPF_MAP_TYPE_HASH);
76 | __type(key, struct hc_key);
77 | __type(value, __u32);
78 | __uint(max_entries, MAX_VIPS);
79 | __uint(map_flags, NO_FLAGS);
80 | } hc_key_map SEC(".maps");
81 |
82 | #endif // of __HEALTHCHECKING_MAPS_H
83 |
--------------------------------------------------------------------------------
/katran/lib/xdproot.cpp:
--------------------------------------------------------------------------------
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
19 | #include
20 |
21 | #include "katran/lib/BpfAdapter.h"
22 |
23 | DEFINE_string(intf, "eth0", "default interface");
24 | DEFINE_string(bpfprog, "xdp_root.o", "path to bpf program");
25 | DEFINE_string(
26 | bpfpath,
27 | "/mnt/bpf/xdproot/xdproot_array",
28 | "path to where we want to pin root_array");
29 | DEFINE_int32(xdp_flags, 0, "xdp attachment flags");
30 |
31 | int main(int argc, char** argv) {
32 | gflags::ParseCommandLineFlags(&argc, &argv, true);
33 | google::InitGoogleLogging(argv[0]);
34 | bool shared_map_found = false;
35 | katran::BpfAdapter adapter;
36 | int err;
37 | auto array_id = adapter.getPinnedBpfObject(FLAGS_bpfpath);
38 | if (array_id > 0) {
39 | LOG(INFO) << "using shared map for root array";
40 | adapter.updateSharedMap("root_array", array_id);
41 | shared_map_found = true;
42 | }
43 | err = adapter.loadBpfProg(FLAGS_bpfprog);
44 | if (err) {
45 | std::cout << "cant load bpf prog " << FLAGS_bpfprog << std::endl;
46 | return 1;
47 | }
48 |
49 | auto prog_fd = adapter.getProgFdByName("xdp_root");
50 | if (prog_fd < 0) {
51 | std::cout << "can't get prog_fd\n";
52 | return 1;
53 | }
54 |
55 | // attaching prog to eth0
56 | if (adapter.detachXdpProg(FLAGS_intf, FLAGS_xdp_flags)) {
57 | std::cout << "can't detach xdp prog\n";
58 | return 1;
59 | }
60 |
61 | if (adapter.attachXdpProg(prog_fd, FLAGS_intf, FLAGS_xdp_flags)) {
62 | std::cout << "cant attach bpf to interface " << FLAGS_intf << std::endl;
63 | return 1;
64 | }
65 |
66 | // map pinning
67 | auto root_array = adapter.getMapFdByName("root_array");
68 | if (root_array < 0) {
69 | std::cout << "can't get fd for vip_map\n";
70 | return 1;
71 | }
72 | if (!shared_map_found) {
73 | auto res = adapter.pinBpfObject(root_array, FLAGS_bpfpath);
74 | if (res < 0) {
75 | std::cout << "can't pin root array\n";
76 | return 1;
77 | }
78 | }
79 |
80 | return 0;
81 | }
82 |
--------------------------------------------------------------------------------
/katran/decap/XdpDecap.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include "katran/decap/XdpDecapStructs.h"
20 | #include "katran/lib/BpfAdapter.h"
21 |
22 | namespace katran {
23 |
24 | class XdpDecap {
25 | public:
26 | XdpDecap() = delete;
27 | /**
28 | * @param XdpDecapConfig& config main configuration of XdpDecap
29 | */
30 | explicit XdpDecap(const XdpDecapConfig& config);
31 |
32 | ~XdpDecap();
33 |
34 | /**
35 | * helper function to load decapsulator into kernel
36 | */
37 | void loadXdpDecap();
38 |
39 | /**
40 | * helper function to attach XdpDecap
41 | */
42 | void attachXdpDecap();
43 |
44 | /**
45 | * @return decap_stats main stats of XdpDecap
46 | *
47 | * helper function to get XdpDecap stats on how many packets were
48 | * decapsulated and processed (processed one contains both decapsulated and
49 | * passed as is)
50 | */
51 | decap_stats getXdpDecapStats();
52 |
53 | /**
54 | * @return int fd of loaded XdpDecap program
55 | *
56 | * helper function to get descriptor of XdpDecap program
57 | */
58 | int getXdpDecapFd() {
59 | return bpfAdapter_.getProgFdByName("xdpdecap");
60 | }
61 |
62 | // Used only for unit testing
63 | // Updates server-id in bpf sever-id-map
64 | void setSeverId(int id);
65 |
66 | private:
67 | /**
68 | * main configuration
69 | */
70 | XdpDecapConfig config_;
71 |
72 | /**
73 | * bpf adapter to interact w/ BPF subsystem
74 | */
75 | BpfAdapter bpfAdapter_;
76 |
77 | /**
78 | * flag which indicates were XdpDecap attached as standalone program or not
79 | * in standalone mode xdpdecap would try to install xdp program to physical
80 | * interface directly. in shared (!standalone) it would try to register itself
81 | * into provided bpf's program array on specified position
82 | */
83 | bool isStandalone_{true};
84 |
85 | /**
86 | * flag which indicate if XdpDecap were loaded into kernel or not
87 | */
88 | bool isLoaded_{false};
89 |
90 | /**
91 | * flag which indicates if XdpDecap were attached
92 | */
93 | bool isAttached_{false};
94 | };
95 |
96 | } // namespace katran
97 |
--------------------------------------------------------------------------------
/katran/lib/bpf/control_data_maps.h:
--------------------------------------------------------------------------------
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 | #ifndef __CONTROL_DATA_MAPS_H
18 | #define __CONTROL_DATA_MAPS_H
19 |
20 | /*
21 | * This file contains definition of maps used for passing of control data and
22 | * information about encapsulation / decapsulation
23 | */
24 |
25 | #include "katran/lib/linux_includes/bpf.h"
26 | #include "katran/lib/linux_includes/bpf_helpers.h"
27 |
28 | #include "katran/lib/bpf/balancer_consts.h"
29 | #include "katran/lib/bpf/balancer_structs.h"
30 |
31 | // control array. contains metadata such as default router mac
32 | // and/or interfaces ifindexes
33 | // indexes:
34 | // 0 - default's mac
35 | struct {
36 | __uint(type, BPF_MAP_TYPE_ARRAY);
37 | __type(key, __u32);
38 | __type(value, struct ctl_value);
39 | __uint(max_entries, CTL_MAP_SIZE);
40 | __uint(map_flags, NO_FLAGS);
41 | } ctl_array SEC(".maps");
42 |
43 | #ifdef KATRAN_INTROSPECTION
44 |
45 | struct {
46 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
47 | __type(key, int);
48 | __type(value, __u32);
49 | __uint(max_entries, MAX_SUPPORTED_CPUS);
50 | __uint(map_flags, NO_FLAGS);
51 | } event_pipe SEC(".maps");
52 |
53 | #endif
54 |
55 | #ifdef INLINE_DECAP_GENERIC
56 | struct {
57 | __uint(type, BPF_MAP_TYPE_HASH);
58 | __type(key, struct address);
59 | __type(value, __u32);
60 | __uint(max_entries, MAX_VIPS);
61 | __uint(map_flags, NO_FLAGS);
62 | } decap_dst SEC(".maps");
63 |
64 | struct {
65 | __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
66 | __type(key, __u32);
67 | __type(value, __u32);
68 | __uint(max_entries, SUBPROGRAMS_ARRAY_SIZE);
69 | } subprograms SEC(".maps");
70 | #endif
71 |
72 | #if defined(GUE_ENCAP) || defined(DECAP_STRICT_DESTINATION)
73 | // map which src ip address for outer ip packet while using GUE encap
74 | // NOTE: This is not a stable API. This is to be reworked when static
75 | // variables will be available in mainline kernels
76 | struct {
77 | __uint(type, BPF_MAP_TYPE_ARRAY);
78 | __type(key, __u32);
79 | __type(value, struct real_definition);
80 | __uint(max_entries, 2);
81 | __uint(map_flags, NO_FLAGS);
82 |
83 | } pckt_srcs SEC(".maps");
84 | #endif
85 |
86 | #endif // of __CONTROL_DATA_MAPS_H
87 |
--------------------------------------------------------------------------------
/katran/lib/Netlink.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | namespace katran {
24 | class NetlinkMessage {
25 | public:
26 | /**
27 | * Constructs a netlink message used to control the lifecycle of a BPF
28 | * program on the network scheduler.
29 | *
30 | * @param seq Sequence number for message.
31 | * @param cmd The rtnetlink command (refer to linux/rtnetlink.h)
32 | * @param flags Netlink flags (refer to linux/netlink.h)
33 | * @param priority Priority of message, used as major number in TC
34 | * handle.
35 | * @param prog_fd FD of loaded BPF program.
36 | * @param ifindex Network interface index
37 | * @param bpf_name Name of bpf program (for identification purposes)
38 | * @param direction Ingress or egress
39 | * @param handle tc-bpf filter handle
40 | */
41 | static NetlinkMessage TC(
42 | unsigned seq,
43 | int cmd,
44 | unsigned flags,
45 | uint32_t priority,
46 | int prog_fd,
47 | unsigned ifindex,
48 | const std::string& bpf_name,
49 | int direction,
50 | const uint32_t handle = 0);
51 |
52 | /**
53 | * Constructs a netlink message used to attach clsact qdisk
54 | * to specified interface
55 | *
56 | * @param ifindex Network interface index
57 | */
58 | static NetlinkMessage QD(unsigned ifindex);
59 |
60 | /**
61 | * Constructs a netlink message used to control the lifecycle of an XDP BPF
62 | * program on a given interface
63 | *
64 | * @param seq Sequence number for the Netlink message
65 | * @param prog_fd FD for the BPF program.
66 | * @param ifindex Network interface index
67 | * @param flags Optional XDP flags.
68 | */
69 | static NetlinkMessage
70 | XDP(unsigned seq, int prog_fd, unsigned ifindex, uint32_t flags);
71 |
72 | const uint8_t* data() const {
73 | return buf_.data();
74 | }
75 |
76 | size_t size() const {
77 | return buf_.size();
78 | }
79 |
80 | unsigned seq() const;
81 |
82 | private:
83 | NetlinkMessage();
84 | std::vector buf_;
85 | };
86 | } // namespace katran
87 |
--------------------------------------------------------------------------------
/example_grpc/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.9)
2 | project(katran_grpc)
3 | set (CMAKE_CXX_STANDARD 17)
4 |
5 | find_library(PROTOBUF libprotobuf.a protobuf)
6 | set(GRPC_BUILD_PATH "${CMAKE_PREFIX_PATH}/grpc/_build")
7 |
8 | find_library(LIBIBERTY libiberty.a iberty)
9 | find_library(DL dl)
10 | find_library(EVENT libevent.a event)
11 | find_package(Protobuf REQUIRED)
12 | find_package(gRPC CONFIG REQUIRED)
13 |
14 | set(PROTO_PATH "${CMAKE_SOURCE_DIR}/example_grpc/protos")
15 | set(KATRAN_PROTO "${PROTO_PATH}/katran.proto")
16 | set(GENERATED_PROTOBUF_PATH "${CMAKE_BINARY_DIR}/generated")
17 | file(MAKE_DIRECTORY ${GENERATED_PROTOBUF_PATH})
18 |
19 | set(KATRAN_PB_CPP_FILE "${GENERATED_PROTOBUF_PATH}/katran.pb.cc")
20 | set(KATRAN_PB_H_FILE "${GENERATED_PROTOBUF_PATH}/katran.pb.h")
21 | set(KATRAN_GRPC_PB_CPP_FILE "${GENERATED_PROTOBUF_PATH}/katran.grpc.pb.cc")
22 | set(KATRAN_GRPC_PB_H_FILE "${GENERATED_PROTOBUF_PATH}/katran.grpc.pb.h")
23 | message("cmd is ${PROTOBUF_PROTOC_EXECUTABLE}")
24 | add_custom_command(
25 | OUTPUT "${KATRAN_PB_H_FILE}"
26 | "${KATRAN_PB_CPP_FILE}"
27 | "${KATRAN_GRPC_PB_H_FILE}"
28 | "${KATRAN_GRPC_PB_CPP_FILE}"
29 | COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
30 | ARGS "--proto_path=${PROTO_PATH}"
31 | "--cpp_out=${GENERATED_PROTOBUF_PATH}"
32 | "${KATRAN_PROTO}"
33 | COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
34 | ARGS "--proto_path=${PROTO_PATH}"
35 | "--grpc_out=${GENERATED_PROTOBUF_PATH}"
36 | "--plugin=protoc-gen-grpc=${GRPC_BUILD_PATH}/grpc_cpp_plugin"
37 | "${KATRAN_PROTO}"
38 | COMMENT "generating grpc files"
39 | )
40 | set(GENERATED_PROTOBUF_FILES ${KATRAN_PB_H_FILE} ${KATRAN_PB_CPP_FILE}
41 | ${KATRAN_GRPC_PB_H_FILE} ${KATRAN_GRPC_PB_CPP_FILE})
42 |
43 | include_directories(${GENERATED_PROTOBUF_PATH})
44 |
45 | add_library(katran_service_handler
46 | "KatranGrpcService.h"
47 | "KatranGrpcService.cpp"
48 | ${GENERATED_PROTOBUF_FILES}
49 | )
50 |
51 | target_link_libraries(katran_service_handler
52 | katranlb
53 | mac_helpers
54 | "Folly::folly"
55 | )
56 |
57 | add_library(grpc_signal_handler
58 | GrpcSignalHandler.cpp
59 | GrpcSignalHandler.h
60 | )
61 |
62 | target_link_libraries(grpc_signal_handler
63 | "Folly::folly"
64 | "${DL}"
65 | gRPC::grpc++
66 | gRPC::gpr
67 | )
68 |
69 | add_executable(katran_server_grpc katran_server.cpp)
70 | target_link_libraries(katran_server_grpc
71 | "-Wl,--start-group"
72 | "${LIBUNWIND}"
73 | "${PROTOBUF}"
74 | "Folly::folly"
75 | "glog::glog"
76 | "${GFLAGS}"
77 | "${PTHREAD}"
78 | "${LIBDC}"
79 | "${DL}"
80 | "${LIBIBERTY}"
81 | "${LIBZ}"
82 | katran_service_handler
83 | grpc_signal_handler
84 | gRPC::grpc++
85 | gRPC::gpr
86 | gRPC::grpc_unsecure
87 | # absl is from grpc
88 | absl::base
89 | absl::cord
90 | absl::node_hash_set
91 | absl::random_random
92 | absl::statusor
93 | "-Wl,--end-group"
94 | )
95 |
96 | install(TARGETS katran_server_grpc
97 | DESTINATION example
98 | )
99 |
--------------------------------------------------------------------------------
/tools/start_katran/start_katran/src/start_katran/default_watcher/default_watcher.go:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2019-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 | package default_watcher
18 |
19 | import (
20 | "bytes"
21 | "log"
22 | "os/exec"
23 | "start_katran/katranc"
24 | "strings"
25 | "time"
26 | )
27 |
28 | const (
29 | GET_DEFAULT_IP_ADDRESS string = "route show default"
30 | PING_CMD string = "-c 1 -q -w 1 "
31 | MAC_CMD string = "neighbor show "
32 | )
33 |
34 | func getCmdOutput(binary_name string, args string) string {
35 | var out bytes.Buffer
36 | args_slice := strings.Fields(args)
37 | cmd := exec.Command(binary_name, args_slice...)
38 | cmd.Stdout = &out
39 | err := cmd.Run()
40 | if err != nil {
41 | log.Printf("error while running %s w/ args %s: %v\n",
42 | cmd, args, err)
43 | return ""
44 | }
45 | return out.String()
46 |
47 | }
48 |
49 | func getDefaultGatewayIp() string {
50 | ip_line := getCmdOutput("ip", GET_DEFAULT_IP_ADDRESS)
51 | if len(ip_line) == 0 {
52 | return ip_line
53 | }
54 | ip_line_slice := strings.Fields(ip_line)
55 | // we are expecting for ip line to looks like something like
56 | // default via 10.0.2.2 dev enp0s3 proto dhcp src 10.0.2.15 metric 100
57 | if len(ip_line_slice) < 3 {
58 | return ""
59 | }
60 | return ip_line_slice[2]
61 | }
62 |
63 | func pingIp(ip string) {
64 | args := PING_CMD + ip
65 | getCmdOutput("ping", args)
66 | }
67 |
68 | func getDefaultMac(ip string) string {
69 | args := MAC_CMD + ip
70 | out := getCmdOutput("ip", args)
71 | if len(out) == 0 {
72 | return out
73 | }
74 | out_slice := strings.Fields(out)
75 | // expecing to see something like
76 | // 10.0.2.2 dev enp0s3 lladdr 52:54:00:12:35:02 REACHABLE
77 | if len(out_slice) < 5 {
78 | return ""
79 | }
80 | return out_slice[4]
81 | }
82 |
83 | func GetDefaultGatewayMac() string {
84 | ip := getDefaultGatewayIp()
85 | pingIp(ip)
86 | return getDefaultMac(ip)
87 | }
88 |
89 | func CheckDefaultGwMac(kc *katranc.KatranClient, mac string) {
90 | current_mac := mac
91 | for {
92 | new_mac := GetDefaultGatewayMac()
93 | if len(new_mac) > 0 && current_mac != new_mac {
94 | kc.ChangeMac(new_mac)
95 | current_mac = new_mac
96 | }
97 | time.Sleep(1 * time.Minute)
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/katran/lib/tests/PipeWriterTest.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2004-present Facebook. All Rights Reserved.
2 |
3 | #include "katran/lib/PipeWriter.h"
4 | #include
5 | #include
6 |
7 | using namespace ::testing;
8 |
9 | namespace {
10 | class TestReadCallback : public folly::AsyncReader::ReadCallback {
11 | public:
12 | bool isBufferMovable() noexcept override {
13 | return true;
14 | }
15 |
16 | void readBufferAvailable(
17 | std::unique_ptr readBuf) noexcept override {
18 | readBuffer_.append(std::move(readBuf));
19 | }
20 |
21 | void readDataAvailable(size_t len) noexcept override {
22 | readBuffer_.postallocate(len);
23 | }
24 |
25 | void getReadBuffer(void** bufReturn, size_t* lenReturn) noexcept override {
26 | auto res = readBuffer_.preallocate(4000, 65000);
27 | *bufReturn = res.first;
28 | *lenReturn = res.second;
29 | }
30 |
31 | void readEOF() noexcept override {}
32 |
33 | void readErr(const folly::AsyncSocketException&) noexcept override {
34 | error_ = true;
35 | }
36 |
37 | std::string getData() {
38 | auto buf = readBuffer_.move();
39 | buf->coalesce();
40 | return std::string((char*)buf->data(), buf->length());
41 | }
42 |
43 | folly::IOBufQueue readBuffer_{folly::IOBufQueue::cacheChainLength()};
44 | bool error_{false};
45 | };
46 |
47 | class PipeWriterTest : public Test {
48 | public:
49 | void SetUp() override {
50 | int rc = pipe2(pipeFds_, O_NONBLOCK);
51 | EXPECT_EQ(rc, 0);
52 | reader_ = folly::AsyncPipeReader::newReader(
53 | &evb_, folly::NetworkSocket::fromFd(pipeFds_[0]));
54 | auto writer = folly::AsyncPipeWriter::newWriter(
55 | &evb_, folly::NetworkSocket::fromFd(pipeFds_[1]));
56 | writer_ = std::move(writer);
57 | }
58 |
59 | protected:
60 | folly::EventBase evb_;
61 | int pipeFds_[2];
62 | folly::AsyncPipeReader::UniquePtr reader_{nullptr};
63 | std::shared_ptr writer_{nullptr};
64 | TestReadCallback readCallback_;
65 | };
66 |
67 | } // namespace
68 |
69 | TEST_F(PipeWriterTest, SimpleWrite) {
70 | katran::PipeWriter pipeWriter;
71 | std::string buf = "ramen";
72 | reader_->setReadCB(&readCallback_);
73 | pipeWriter.setWriterDestination(writer_);
74 | pipeWriter.writeData(buf.c_str(), buf.size());
75 | evb_.loopOnce();
76 | pipeWriter.stop();
77 | EXPECT_EQ(readCallback_.getData(), "ramen");
78 | EXPECT_FALSE(readCallback_.error_);
79 | EXPECT_EQ(pipeWriter.getWrites(), 1);
80 | EXPECT_EQ(pipeWriter.getErrs(), 0);
81 | }
82 |
83 | TEST_F(PipeWriterTest, WriteAfterStop) {
84 | katran::PipeWriter pipeWriter;
85 | std::string buf = "ramen";
86 | reader_->setReadCB(&readCallback_);
87 | pipeWriter.setWriterDestination(writer_);
88 | pipeWriter.writeData(buf.c_str(), buf.size());
89 | pipeWriter.stop();
90 | pipeWriter.writeData(buf.c_str(), buf.size());
91 | evb_.loopOnce();
92 | EXPECT_EQ(readCallback_.getData(), "ramen");
93 | EXPECT_FALSE(readCallback_.error_);
94 | EXPECT_EQ(pipeWriter.getWrites(), 1);
95 | EXPECT_EQ(pipeWriter.getErrs(), 0);
96 | }
97 |
--------------------------------------------------------------------------------
/tools/xdpdump/XdpEventLogger.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include "tools/xdpdump/XdpDumpStructs.h"
21 |
22 | namespace xdpdump {
23 |
24 | struct XdpEventInfo {
25 | uint32_t data_len{0};
26 | uint32_t hdr_size{0};
27 | uint32_t pkt_size{0};
28 | };
29 |
30 | class XdpEventLogger {
31 | public:
32 | /**
33 | * @param bool mute set true if logger shouldn't write any data into out
34 | * @param std::ostream& out is an ostream where logs are saved
35 | *
36 | * Constructor for XdpEventLogger
37 | */
38 | explicit XdpEventLogger(bool mute, std::ostream& out)
39 | : mute_(mute), out_(out) {}
40 |
41 | /**
42 | * Virtual destructor
43 | */
44 | virtual ~XdpEventLogger() = default;
45 |
46 | /**
47 | * @param const char* data received from the XDP prog.
48 | *
49 | * Function that processes handleEvent, produces XdpEventInfo, and,
50 | * if required, logs some data.
51 | */
52 | virtual XdpEventInfo handlePerfEvent(const char* data) = 0;
53 |
54 | protected:
55 | /*
56 | * @param uint8_t const* v6 is an array of 16 bytes
57 | *
58 | * Converts bytes of IPv6 address into the std::string
59 | */
60 | static std::string binaryToV6String(uint8_t const* v6);
61 |
62 | /*
63 | * @param uint32_t v4 is an IPv4 address
64 | *
65 | * Converts IPv4 address presented by uint32 into the std::string
66 | */
67 | static std::string longToV4String(uint32_t v4);
68 |
69 | /**
70 | * mute_ set true if logger shouldn't write any data into out_
71 | */
72 | const bool mute_{false};
73 |
74 | /**
75 | * out_ is a stream where all information will be logged in.
76 | */
77 | std::ostream& out_;
78 | };
79 |
80 | class ProgLogger : public XdpEventLogger {
81 | public:
82 | /**
83 | * @param bool mute set if logger should write any data into out
84 | * @param std::ostream& out is an ostream where logs are saved
85 | *
86 | * Constructor for ProgLogger
87 | */
88 | ProgLogger(bool mute, std::ostream& out) : XdpEventLogger(mute, out) {}
89 |
90 | /**
91 | * @param const char* data received from the XDP prog.
92 | *
93 | * Overrides XdpEventLogger::handlePerfEvent
94 | */
95 | virtual XdpEventInfo handlePerfEvent(const char* data) override;
96 |
97 | private:
98 | /**
99 | * @param XdpDumpOutput* msg
100 | *
101 | * Logs prog data
102 | */
103 | void log(const XdpDumpOutput* msg);
104 | };
105 | } // namespace xdpdump
106 |
--------------------------------------------------------------------------------
/katran/decap/tc_bpf/tc_decap_stats_maps.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2019-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 | #ifndef __DECAP_STATS_MAPS_H
18 | #define __DECAP_STATS_MAPS_H
19 |
20 | #include "katran/lib/linux_includes/bpf.h"
21 | #include "katran/lib/linux_includes/bpf_helpers.h"
22 |
23 | #include "katran/lib/bpf/balancer_consts.h"
24 | #include "katran/lib/bpf/balancer_structs.h"
25 |
26 | #ifndef DECAP_STATS_MAP_SIZE
27 | #define DECAP_STATS_MAP_SIZE 1
28 | #endif
29 |
30 | struct decap_tpr_stats {
31 | __u64 tpr_misrouted;
32 | __u64 tpr_total;
33 | };
34 |
35 | struct vip6_addr {
36 | __be32 vip6_addr[4];
37 | };
38 |
39 | struct vip4_addr {
40 | __be32 vip_addr;
41 | };
42 |
43 | struct vip_info {
44 | __u8 proto_mask;
45 | };
46 |
47 | struct vip_decap_stats {
48 | __u64 v4_packets;
49 | __u64 v6_packets;
50 | };
51 |
52 | // map for tpr related counters
53 | struct {
54 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
55 | __type(key, __u32);
56 | __type(value, struct decap_tpr_stats);
57 | __uint(max_entries, DECAP_STATS_MAP_SIZE);
58 | __uint(map_flags, NO_FLAGS);
59 | } tc_tpr_stats SEC(".maps");
60 |
61 | // map, which contains server_id info
62 | struct {
63 | __uint(type, BPF_MAP_TYPE_ARRAY);
64 | __type(key, __u32);
65 | __type(value, __u32);
66 | __uint(max_entries, 2);
67 | __uint(map_flags, NO_FLAGS);
68 | } tpr_server_ids SEC(".maps");
69 |
70 | // map for sampled tpr mismatched server ids
71 | struct {
72 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
73 | __type(key, __u32);
74 | __type(value, __u64);
75 | __uint(max_entries, DECAP_STATS_MAP_SIZE);
76 | __uint(map_flags, NO_FLAGS);
77 | } tpr_mism_sid SEC(".maps");
78 |
79 | // v6 vip info
80 | struct {
81 | __uint(type, BPF_MAP_TYPE_HASH);
82 | __type(key, struct vip6_addr);
83 | __type(value, struct vip_info);
84 | __uint(max_entries, MAX_VIPS);
85 | __uint(map_flags, NO_FLAGS);
86 | } tc_vip6_info SEC(".maps");
87 |
88 | // v4 vip info
89 | struct {
90 | __uint(type, BPF_MAP_TYPE_HASH);
91 | __type(key, struct vip4_addr);
92 | __type(value, struct vip_info);
93 | __uint(max_entries, MAX_VIPS);
94 | __uint(map_flags, NO_FLAGS);
95 | } tc_vip4_info SEC(".maps");
96 |
97 | // per cpu vip decap counters
98 | // key 0/1 for tcp/udp proto
99 | struct {
100 | __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
101 | __type(key, __u32);
102 | __type(value, struct vip_decap_stats);
103 | __uint(max_entries, 2);
104 | __uint(map_flags, NO_FLAGS);
105 | } tc_vip_stats SEC(".maps");
106 |
107 | #endif // of __DECAP_STATS_MAPS_H
108 |
--------------------------------------------------------------------------------
/katran/lib/KatranSimulatorUtils.h:
--------------------------------------------------------------------------------
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 | #pragma once
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | namespace katran {
25 |
26 | /**
27 | * struct that contains all the fields that uniquely identifies a flow
28 | */
29 | struct KatranFlow {
30 | // source ip address of the packet
31 | std::string src;
32 | // destination ip address of the packet
33 | std::string dst;
34 | uint16_t srcPort;
35 | uint16_t dstPort;
36 | // protocol number (e.g. 6 for TCP, 17 for UDP)
37 | uint8_t proto;
38 | };
39 |
40 | class KatranSimulatorUtils {
41 | public:
42 | /**
43 | * Create an IPv4 packet with the specified parameters
44 | */
45 | static void createV4Packet(
46 | const folly::IPAddress& src,
47 | const folly::IPAddress& dst,
48 | std::unique_ptr& buf,
49 | uint8_t proto,
50 | uint16_t size,
51 | uint8_t ttl);
52 |
53 | /**
54 | * Create an IPv6 packet with the specified parameters
55 | */
56 | static void createV6Packet(
57 | const folly::IPAddress& src,
58 | const folly::IPAddress& dst,
59 | std::unique_ptr& buf,
60 | uint8_t proto,
61 | uint16_t size,
62 | uint8_t ttl);
63 |
64 | /**
65 | * Create a packet from a KatranFlow specification
66 | */
67 | static std::unique_ptr createPacketFromFlow(
68 | const KatranFlow& flow,
69 | uint16_t packetSize,
70 | uint8_t ttl = 64);
71 |
72 | /**
73 | * Create TCP header in the packet buffer
74 | */
75 | static void createTcpHeader(
76 | std::unique_ptr& buf,
77 | uint16_t srcPort,
78 | uint16_t dstPort,
79 | uint16_t offset);
80 |
81 | /**
82 | * Create UDP header in the packet buffer
83 | */
84 | static void createUdpHeader(
85 | std::unique_ptr& buf,
86 | uint16_t srcPort,
87 | uint16_t dstPort,
88 | uint16_t offset,
89 | uint16_t size);
90 |
91 | /**
92 | * Get the destination IP address from a packet
93 | */
94 | static std::string getPcktDst(std::unique_ptr& pckt);
95 |
96 | /**
97 | * Convert IPv4 address to string
98 | */
99 | static const std::string toV4String(uint32_t addr);
100 |
101 | /**
102 | * Convert IPv6 address to string
103 | */
104 | static const std::string toV6String(uint8_t const* v6);
105 | };
106 |
107 | } // namespace katran
108 |
--------------------------------------------------------------------------------
/katran/lib/linux_includes/jhash.h:
--------------------------------------------------------------------------------
1 | #ifndef _JHASH_KERNEL_
2 | #define _JHASH_KERNEL_
3 | /* copy paste of jhash from kernel sources to make sure llvm
4 | * can compile it into valid sequence of bpf instructions
5 | */
6 |
7 | static inline __u32 rol32(__u32 word, unsigned int shift) {
8 | return (word << shift) | (word >> ((-shift) & 31));
9 | }
10 |
11 | #define __jhash_mix(a, b, c) \
12 | { \
13 | a -= c; \
14 | a ^= rol32(c, 4); \
15 | c += b; \
16 | b -= a; \
17 | b ^= rol32(a, 6); \
18 | a += c; \
19 | c -= b; \
20 | c ^= rol32(b, 8); \
21 | b += a; \
22 | a -= c; \
23 | a ^= rol32(c, 16); \
24 | c += b; \
25 | b -= a; \
26 | b ^= rol32(a, 19); \
27 | a += c; \
28 | c -= b; \
29 | c ^= rol32(b, 4); \
30 | b += a; \
31 | }
32 |
33 | #define __jhash_final(a, b, c) \
34 | { \
35 | c ^= b; \
36 | c -= rol32(b, 14); \
37 | a ^= c; \
38 | a -= rol32(c, 11); \
39 | b ^= a; \
40 | b -= rol32(a, 25); \
41 | c ^= b; \
42 | c -= rol32(b, 16); \
43 | a ^= c; \
44 | a -= rol32(c, 4); \
45 | b ^= a; \
46 | b -= rol32(a, 14); \
47 | c ^= b; \
48 | c -= rol32(b, 24); \
49 | }
50 |
51 | #define JHASH_INITVAL 0xdeadbeef
52 |
53 | typedef unsigned int u32;
54 |
55 | static inline u32 jhash(const void* key, u32 length, u32 initval) {
56 | u32 a, b, c;
57 | const unsigned char* k = key;
58 |
59 | a = b = c = JHASH_INITVAL + length + initval;
60 |
61 | while (length > 12) {
62 | a += *(u32*)(k);
63 | b += *(u32*)(k + 4);
64 | c += *(u32*)(k + 8);
65 | __jhash_mix(a, b, c);
66 | length -= 12;
67 | k += 12;
68 | }
69 | switch (length) {
70 | case 12:
71 | c += (u32)k[11] << 24;
72 | case 11:
73 | c += (u32)k[10] << 16;
74 | case 10:
75 | c += (u32)k[9] << 8;
76 | case 9:
77 | c += k[8];
78 | case 8:
79 | b += (u32)k[7] << 24;
80 | case 7:
81 | b += (u32)k[6] << 16;
82 | case 6:
83 | b += (u32)k[5] << 8;
84 | case 5:
85 | b += k[4];
86 | case 4:
87 | a += (u32)k[3] << 24;
88 | case 3:
89 | a += (u32)k[2] << 16;
90 | case 2:
91 | a += (u32)k[1] << 8;
92 | case 1:
93 | a += k[0];
94 | __jhash_final(a, b, c);
95 | case 0: /* Nothing left to add */
96 | break;
97 | }
98 |
99 | return c;
100 | }
101 |
102 | static inline u32 __jhash_nwords(u32 a, u32 b, u32 c, u32 initval) {
103 | a += initval;
104 | b += initval;
105 | c += initval;
106 | __jhash_final(a, b, c);
107 | return c;
108 | }
109 |
110 | static inline u32 jhash_2words(u32 a, u32 b, u32 initval) {
111 | return __jhash_nwords(a, b, 0, initval + JHASH_INITVAL + (2 << 2));
112 | }
113 |
114 | static inline u32 jhash_1word(u32 a, u32 initval) {
115 | return __jhash_nwords(a, 0, 0, initval + JHASH_INITVAL + (1 << 2));
116 | }
117 |
118 | #endif
119 |
--------------------------------------------------------------------------------
/katran/tpr/TPRTypes.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #pragma once
4 |
5 | #include
6 | #include
7 |
8 | namespace katran_tpr {
9 |
10 | constexpr int kNoFlags = 0;
11 |
12 | // For consistency, denote server-mode as 1 and client mode as 0.
13 | constexpr uint8_t kServerMode = 1;
14 | constexpr uint8_t kClientMode = 0;
15 |
16 | enum class RunningMode : uint8_t {
17 | DEFAULT_RESERVED = 0,
18 | SERVER = 1,
19 | CLIENT = 2
20 | };
21 |
22 | // Information to set in the TCP header option field.
23 | struct tcp_opt {
24 | uint8_t kind;
25 | uint8_t len;
26 | uint32_t server_id;
27 | };
28 |
29 | // information about the running mode to pass to the bpf program.
30 | struct server_info {
31 | RunningMode running_mode;
32 | uint8_t kde_enabled;
33 | uint8_t kde_zones;
34 | // only ipv6 is supported
35 | uint32_t server_id;
36 | // when default server id is not available, backend uses server id v2 as
37 | // fallback
38 | uint32_t server_id_fallback;
39 | };
40 |
41 | // Tentative stats for different transport events
42 | struct tcp_router_stats {
43 | uint64_t server_id_read{0};
44 | uint64_t server_id_set{0};
45 | uint64_t conns_skipped{0};
46 | uint64_t no_tcp_opt_hdr{0};
47 | uint64_t error_bad_id{0};
48 | uint64_t error_server_id_zero{0};
49 | uint64_t error_write_opt{0};
50 | uint64_t error_sys_calls{0};
51 | uint64_t ignoring_due_to_kde{0};
52 | uint64_t server_opt{0};
53 | };
54 |
55 | // helper methods to constructs useful error message without boiler plate code.
56 | inline folly::Unexpected makeError(
57 | int errorCode,
58 | const std::string& entity,
59 | const std::string& reason) noexcept {
60 | const std::string& errorMsg = fmt::format("Failed to {}: {}", entity, reason);
61 | return folly::makeUnexpected(
62 | std::system_error(errorCode, std::generic_category(), errorMsg));
63 | }
64 |
65 | inline folly::Unexpected makeError(
66 | const std::system_error& other,
67 | const std::string& entity) noexcept {
68 | const std::string& errorMsg =
69 | fmt::format("Failed to {}: {}", entity, other.what());
70 | return folly::makeUnexpected(std::system_error(other.code(), errorMsg));
71 | }
72 |
73 | inline bool operator==(RunningMode lhs, RunningMode rhs) {
74 | return static_cast(lhs) == static_cast(rhs);
75 | }
76 |
77 | inline std::ostream& operator<<(std::ostream& os, const RunningMode& mode) {
78 | switch (mode) {
79 | case RunningMode::CLIENT:
80 | os << "CLIENT";
81 | break;
82 | case RunningMode::SERVER:
83 | os << "SERVER";
84 | break;
85 | default:
86 | os << "Unknown running mode.";
87 | }
88 | return os;
89 | }
90 |
91 | inline std::ostream& operator<<(std::ostream& os, const tcp_router_stats& s) {
92 | os << "server_id_read=" << s.server_id_read
93 | << " server_id_set=" << s.server_id_set
94 | << " conns_skipped=" << s.conns_skipped
95 | << " no_tcp_opt_hdr=" << s.no_tcp_opt_hdr
96 | << " ignoring_kde=" << s.ignoring_due_to_kde
97 | << " error_bad_id=" << s.error_bad_id
98 | << " error_server_id_zero=" << s.error_server_id_zero
99 | << " error_write_opt=" << s.error_write_opt
100 | << " error_sys_calls=" << s.error_sys_calls
101 | << " server_opt=" << s.server_opt;
102 | return os;
103 | }
104 |
105 | } // namespace katran_tpr
106 |
--------------------------------------------------------------------------------
/katran/tpr/bpf_util/BpfUtil.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) Meta Platforms, Inc. and affiliates.
2 |
3 | #include
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include
13 | #include
14 |
15 | extern "C" {
16 | #include
17 | #include
18 | #include
19 | }
20 |
21 | namespace katran_tpr::BpfUtil {
22 |
23 | #if False
24 | static int libbpf_print_fn(
25 | enum libbpf_print_level level,
26 | const char* format,
27 | va_list args) {
28 | return vfprintf(stderr, format, args);
29 | }
30 | #endif
31 |
32 | SystemMaybe init() noexcept {
33 | #if False // Enable to get libbpf internal logs
34 | libbpf_set_print(libbpf_print_fn);
35 | #endif
36 |
37 | VLOG(1) << "Enabled libbpf strict mode";
38 | libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
39 |
40 | return FLAGS_set_rlimit_memlock ? setRLimit() : noSystemError();
41 | }
42 |
43 | SystemMaybe setRLimit() noexcept {
44 | struct rlimit lck_mem = {};
45 | lck_mem.rlim_cur = RLIM_INFINITY;
46 | lck_mem.rlim_max = RLIM_INFINITY;
47 | if (setrlimit(RLIMIT_MEMLOCK, &lck_mem)) {
48 | int savedErrno = errno;
49 | return SYSTEM_ERROR(
50 | savedErrno,
51 | "Error while setting limit for locked memory, error:",
52 | folly::errnoStr(savedErrno));
53 | }
54 | return noSystemError();
55 | }
56 |
57 | int getDirFd(const std::string& path) noexcept {
58 | return ::open(path.c_str(), O_DIRECTORY, O_RDONLY);
59 | }
60 |
61 | SystemMaybe attachCgroupProg(
62 | int progFd,
63 | const std::string& cgroup,
64 | unsigned int flags) noexcept {
65 | auto targetFd = getDirFd(cgroup);
66 | if (targetFd < 0) {
67 | return SYSTEM_ERROR(
68 | EINVAL, fmt::format("Invalid target cgroup dir: {}", cgroup));
69 | }
70 | SCOPE_EXIT {
71 | ::close(targetFd);
72 | };
73 | if (bpf_prog_attach(progFd, targetFd, BPF_CGROUP_SOCK_OPS, flags)) {
74 | int savedErrno = errno;
75 | return SYSTEM_ERROR(
76 | savedErrno,
77 | fmt::format(
78 | "Error while attaching bpf prog fd: {} to cgroup: {}, error {} ",
79 | progFd,
80 | cgroup,
81 | folly::errnoStr(savedErrno)));
82 | }
83 | LOG(INFO) << "Successfully attached bpf prog at cgroup: " << cgroup;
84 | return noSystemError();
85 | }
86 |
87 | SystemMaybe detachCgroupProg(
88 | int progFd,
89 | const std::string& cgroup) noexcept {
90 | auto targetFd = getDirFd(cgroup);
91 | if (targetFd < 0) {
92 | return SYSTEM_ERROR(
93 | EINVAL, fmt::format("Invalid target cgroup dir: {}", cgroup));
94 | }
95 | SCOPE_EXIT {
96 | ::close(targetFd);
97 | };
98 | if (bpf_prog_detach2(progFd, targetFd, BPF_CGROUP_SOCK_OPS)) {
99 | int savedErrno = errno;
100 | return SYSTEM_ERROR(
101 | savedErrno,
102 | fmt::format(
103 | "Error while detaching bpf prog fd: {} to cgroup: {}, error {} ",
104 | progFd,
105 | cgroup,
106 | folly::errnoStr(savedErrno)));
107 | }
108 | VLOG(2) << fmt::format(
109 | "BPF program successfully detached from cgroup: {}", cgroup);
110 | return noSystemError();
111 | }
112 |
113 | } // namespace katran_tpr::BpfUtil
114 |
--------------------------------------------------------------------------------
/katran/lib/EventPipeCallback.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2004-present Facebook. All Rights Reserved.
2 |
3 | #include "katran/lib/EventPipeCallback.h"
4 | #include
5 | #include
6 | #include
7 | #include "katran/lib/PcapStructs.h"
8 |
9 | namespace katran {
10 | namespace monitoring {
11 |
12 | void EventPipeCallback::readBuffer(
13 | std::unique_ptr&& buf) noexcept {
14 | VLOG(4) << __func__ << " ready to send data";
15 | folly::io::Cursor rcursor(buf.get());
16 | size_t rec_hdr_sz = sizeof(pcaprec_hdr_s);
17 |
18 | // Here we enter the loop of reading complete pcap records from the buffer. If
19 | // either the pcap record header or the packet data is incomplete, we break
20 | // the loop and store whatever is left over in the temporary buffer. Although
21 | // there are situations where there's no client, the loop has to run in order
22 | // to maintain bounds between pcap records so that when clients subscribe we
23 | // can respond without worrying about breaking the bounds between two
24 | // consecutive pcap records.
25 | for (;;) {
26 | pcaprec_hdr_s rec_hdr;
27 | Event msg;
28 | if (rcursor.canAdvance(rec_hdr_sz)) {
29 | rec_hdr = rcursor.read();
30 | } else {
31 | // It's an INFO because when rcursor finishes reading message, this is how
32 | // we break the loop
33 | LOG(INFO) << "Can't read rec_hdr_sz, giving up";
34 | break;
35 | }
36 |
37 | if (rcursor.canAdvance(rec_hdr.incl_len)) {
38 | // Back up so that we can include pcap header in data
39 | rcursor.retreat(rec_hdr_sz);
40 | msg.id = event_id_;
41 | msg.pktsize = rec_hdr.orig_len;
42 | msg.data = std::string(
43 | reinterpret_cast(rcursor.data()),
44 | rec_hdr_sz + rec_hdr.incl_len);
45 | rcursor.skip(rec_hdr_sz + rec_hdr.incl_len);
46 | } else {
47 | VLOG(2) << fmt::format(
48 | "incomplete pcap message, expecting {} bytes of data, got {}",
49 | rec_hdr.incl_len,
50 | rcursor.length());
51 | rcursor.retreat(rec_hdr_sz);
52 | break;
53 | }
54 |
55 | // Send data if the event is enabled
56 | if (enabled()) {
57 | auto subsmap = cb_subsmap_.rlock();
58 | for (auto& it : *subsmap) {
59 | VLOG(4) << fmt::format(
60 | "sending event {} to client", toString(event_id_));
61 | it.second->sendEvent(msg);
62 | }
63 | }
64 | }
65 |
66 | // Simply triming the amount of bytes we've read. If there's leftover,
67 | // we should append it to the readBuffer_, which is now empty.
68 | buf->trimStart(rcursor.getCurrentPosition());
69 | if (buf->length() != 0) {
70 | readBuffer_.append(std::move(buf));
71 | }
72 | }
73 |
74 | void EventPipeCallback::addClientSubscription(
75 | std::pair>&& newSub) {
76 | ClientId cid = newSub.first;
77 | VLOG(4) << __func__ << fmt::format(" Adding client {}", cid);
78 | auto cb_subsmap = cb_subsmap_.wlock();
79 | auto result = cb_subsmap->insert(std::move(newSub));
80 | if (!result.second) {
81 | LOG(ERROR) << fmt::format("duplicate client id: {}", cid);
82 | }
83 | }
84 |
85 | void EventPipeCallback::removeClientSubscription(ClientId cid) {
86 | auto cb_subsmap = cb_subsmap_.wlock();
87 | size_t cnt = cb_subsmap->erase(cid);
88 | if (cnt != 1) {
89 | LOG(ERROR) << fmt::format(
90 | "no client subscription associated with id: {}", cid);
91 | }
92 | }
93 |
94 | } // namespace monitoring
95 | } // namespace katran
96 |
--------------------------------------------------------------------------------