├── .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 | --------------------------------------------------------------------------------