tools/xdpdump/XdpDump.h (70 lines of code) (raw):

/* Copyright (C) 2018-present, Facebook, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #pragma once #include <memory> #include <string> #include <thread> #include <vector> #include <bcc/bpf_module.h> #include <folly/MPMCQueue.h> #include <folly/io/async/AsyncSignalHandler.h> #include <folly/io/async/AsyncTimeout.h> #include <folly/io/async/EventBase.h> #include "katran/lib/PcapMsg.h" #include "tools/xdpdump/XdpDumpStructs.h" #include "tools/xdpdump/XdpEventReader.h" namespace folly { class EventBase; } namespace xdpdump { /** * flags which show which field is set in filter struct */ constexpr uint8_t kSrcSet = (1 << 0); constexpr uint8_t kDstSet = (1 << 1); constexpr uint8_t kSportSet = (1 << 2); constexpr uint8_t kDportSet = (1 << 3); constexpr uint8_t kProtoSet = (1 << 4); /** * Main class which implements xdpdump util - tcpdump like util to capture * packets on "XDP level" (as xdp could either drop or tx this packets - we * we wont be able to see em with tcpdump as this packets will never hit * kernel's tcp/ip stack). */ class XdpDump : public folly::AsyncTimeout { public: /** * @param EventBase* eventBase for AsyncTimeout * @param XdpDumpFilter filter * @param std::shared_ptr<PcapWriter> pcapWriter * * we pass filter object which contains all the field (such as src/dst/ * or a line for pcap-based filter) which describes what packets we want to * capture */ explicit XdpDump( folly::EventBase* eventBase, XdpDumpFilter filter, std::shared_ptr<katran::PcapWriter> pcapWriter); /** * Destructor for XdpDump. */ ~XdpDump(); /** * helper function to remove xdpdump from rootlet's root array */ void clear(); /** * helper function which starts xdpdump */ void run(); /** * timeout function */ virtual void timeoutExpired() noexcept override; private: /** * helper class which implements sighandler. this allow us to detach * xdpdump from rootlets array when user decided to stop the program. */ class XdpDumpSignalHandler : public folly::AsyncSignalHandler { public: XdpDumpSignalHandler(folly::EventBase* evb, XdpDump* parent); ~XdpDumpSignalHandler() override {} void signalReceived(int signum) noexcept override; private: XdpDump* parent_; }; /** * helper function which compiles bpf program. */ void compile(); /** * helper function which loads bpf program in kernel */ void load(); /** * helper function which prepares and passing rootlet's prog fd to bpf prog */ void prepareSharedMap(); /** * helper function which retrievs rootlet's jump table fd from pinned map */ void getJmpFd(); /** * helper function to pump eventBase_ */ void pumpEventBase(); /** * helper function which start pcap writer if needed */ void tryStartPcapWriter(); /** * helper function which start perf event reader */ void startEventReaders(); /** * helper function which starts signal handler */ void startSigHandler(); /** * helper function which attaches loaded bpf program to rootlet. */ void attach(); /** * helper function which detaches xdpdump from rootlet's array */ void detach(); /** * as we are doing all the work in separate threads we need to block our main * one. this function is basicaly blocks main thread "waiting for evb to stop" * (which happens only on sigint receiving) */ void sleepForever(); /** * helper function which prepares cflags for bpf prog compilation. * cflags are based on info which has been provided inside XdpDumpFilter * struct */ void prepareCflags(); /** * helper function which stop both pcapWriter (if running) * and detach xdpdump from rootlet */ void stop(); /** * structs which describes in what packets are we interested in * as well as contains some metainfo (such as rootlets map location/ * our position in it/ pcap's file location etc etc etc) */ XdpDumpFilter filter_; /** * pcapWriter is used to store pcap-data into file or byte range. */ std::shared_ptr<katran::PcapWriter> pcapWriter_{nullptr}; /** * bpf provider which is used to created bpf prog. depends on configuration * could be either Bcc or Pcap compiler */ std::unique_ptr<ebpf::BPFModule> bpf_; /** * evbThread, which run all event readers and sighandler. */ std::thread evbThread_; int perfEventMapFd_; /** * bpf prog fd */ int progFd_; /** * fd of rootlet's jump array (array of bpf progs) */ int jmpFd_; /** * vector of eventReaders (there is one event reader per cpu core) */ std::vector<std::unique_ptr<XdpEventReader>> eventReaders_; /** * vector of cflags, which are passed to bpf backedn during compilation phase */ std::vector<std::string> cflags_; std::unique_ptr<XdpDumpSignalHandler> sigHandler_; std::thread writerThread_; /** * MPMCQueue where we pass PcapMsg from perfEventReaders to PcapWriter */ std::shared_ptr<folly::MPMCQueue<katran::PcapMsg>> queue_; /** * name of main bpf function */ std::string funcName_; /** * name of main bpf function */ folly::EventBase* eventBase_; }; } // namespace xdpdump