Skip to content

Commit

Permalink
adding library to do xdp based ipip decapsulation
Browse files Browse the repository at this point in the history
  • Loading branch information
tehnerd committed Feb 6, 2019
1 parent 06d69c4 commit 44546c6
Show file tree
Hide file tree
Showing 14 changed files with 794 additions and 7 deletions.
1 change: 1 addition & 0 deletions build_bpf_modules_opensource.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ rm -rf ./deps/bpfprog
mkdir -p ./deps/bpfprog/include
cp ./katran/lib/Makefile-bpf ./deps/bpfprog/Makefile
cp -r ./katran/lib/bpf ./deps/bpfprog/
cp -r ./katran/decap/bpf ./deps/bpfprog/
cp ./katran/lib/linux_includes/* ./deps/bpfprog/include/
cd ./deps/bpfprog && LD_LIBRARY_PATH="${CLANG_PATH}/lib" make \
EXTRA_CFLAGS="$*" \
Expand Down
1 change: 1 addition & 0 deletions katran/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
cmake_minimum_required (VERSION 3.0)
add_subdirectory(lib)
add_subdirectory(decap)
15 changes: 15 additions & 0 deletions katran/decap/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cmake_minimum_required (VERSION 3.0)
project (libdecap-proj)

add_library(decap STATIC
XdpDecap.cpp
XdpDecap.h
XdpDecapStructs.h
)

target_link_libraries(decap
bpfadapter
"${GLOG}"
)

add_subdirectory(testing)
142 changes: 142 additions & 0 deletions katran/decap/XdpDecap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/* 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.
*/

#include <glog/logging.h>

#include "katran/decap/XdpDecap.h"

namespace katran {

XdpDecap::XdpDecap(const XdpDecapConfig& config) : config_(config) {
if (!config_.mapPath.empty()) {
// sanity checking that interface w/ specified name exists
// so we wont need to do it later every time when we would want to access it
auto ifindex = bpfAdapter_.getInterfaceIndex(config_.interface);
if (!ifindex) {
LOG(FATAL) << "Can not resolve to ifindex interface: "
<< config_.interface;
return;
}
isStandalone_ = false;
}
}

XdpDecap::~XdpDecap() {
if (isAttached_) {
if (isStandalone_) {
auto res = bpfAdapter_.detachXdpProg(config_.interface);
if (res) {
LOG(ERROR) << "Was not able to detach XdpDecap";
}
} else {
auto prog_fd = bpfAdapter_.getPinnedBpfObject(config_.mapPath);
if (prog_fd >= 0) {
auto res = bpfAdapter_.bpfMapDeleteElement(prog_fd, &config_.progPos);
if (res) {
LOG(ERROR) << "Was not able to detach XdpDecap from prog array";
}
}
}
}
}

void XdpDecap::loadXdpDecap() {
if (isLoaded_) {
LOG(ERROR) << "Trying to load alrady attached XdpDecap";
return;
}
auto res = bpfAdapter_.loadBpfProg(config_.progPath);
if (res) {
LOG(FATAL) << "Was not able to load XdpDecap program from "
<< config_.progPath;
// LOG(FATAL) would terminate. return for readability
return;
}
// sanity checking
// check that program w/ expected name has been loaded
if (bpfAdapter_.getProgFdByName("xdp-decap") < 0) {
LOG(FATAL) << "Was not able to find xdp prog w/ name xdp-decap in "
<< config_.progPath;
return;
}

if (bpfAdapter_.getMapFdByName("stats") < 0) {
LOG(FATAL) << "Was not able to find bpf map w/ name stats in "
<< config_.progPath;
return;
}
isLoaded_ = true;
}

void XdpDecap::attachXdpDecap() {
if (!isLoaded_ || isAttached_) {
LOG(FATAL) << "trying to attach non loaded or already attached "
<< "XdpDecap program";
return;
}
auto prog_fd = bpfAdapter_.getProgFdByName("xdp-decap");
if (isStandalone_) {
if (bpfAdapter_.attachXdpProg(prog_fd, config_.interface)) {
LOG(FATAL) << "Was not able to attach XdpDecap to interface "
<< config_.interface;
return;
}
} else {
auto map_fd = bpfAdapter_.getPinnedBpfObject(config_.mapPath);
if (map_fd < 0) {
LOG(FATAL) << "Was not able to get a fd of pinned bpf map "
<< config_.mapPath;
return;
}
if (bpfAdapter_.bpfUpdateMap(map_fd, &config_.progPos, &prog_fd)) {
LOG(FATAL) << "Was not able to update pinned bpf map " << config_.mapPath
<< " with elem on position " << config_.progPos;
return;
}
}
isAttached_ = true;
}

decap_stats XdpDecap::getXdpDecapStats() {
struct decap_stats stats = {};
uint32_t key = 0;

if (!isLoaded_) {
LOG(ERROR) << "Trying to get stats for not loaded XdpDecap program";
return stats;
}
auto nr_cpus = bpfAdapter_.getPossibleCpus();
if (nr_cpus < 0) {
LOG(ERROR) << "Can not figure out number of online cpus";
return stats;
}

struct decap_stats percpu_stats[nr_cpus];

if (!bpfAdapter_.bpfMapLookupElement(
bpfAdapter_.getMapFdByName("stats"), &key, &percpu_stats)) {
for (auto& stat : percpu_stats) {
stats.decap_v4 += stat.decap_v4;
stats.decap_v6 += stat.decap_v6;
stats.total += stat.total;
}
} else {
LOG(ERROR) << "Error while trying to get decap stats";
}
return stats;
}

} // namespace katran
89 changes: 89 additions & 0 deletions katran/decap/XdpDecap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/* 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 "katran/decap/XdpDecapStructs.h"
#include "katran/lib/BpfAdapter.h"

namespace katran {

class XdpDecap {
public:
XdpDecap() = delete;
/**
* @param XdpDecapConfig& config main configuration of XdpDecap
*/
explicit XdpDecap(const XdpDecapConfig& config);

~XdpDecap();

/**
* helper function to load decapsulator into kernel
*/
void loadXdpDecap();

/**
* helper function to attach XdpDecap
*/
void attachXdpDecap();

/**
* @return decap_stats main stats of XdpDecap
*
* helper function to get XdpDecap stats on how many packets were
* decapsulated and processed (processed one contains both decapsulated and
* passed as is)
*/
decap_stats getXdpDecapStats();

/**
* @return int fd of loaded XdpDecap program
*
* helper function to get descriptor of XdpDecap program
*/
int getXdpDecapFd() {
return bpfAdapter_.getProgFdByName("xdp-decap");
}

private:
/**
* main configuration
*/
XdpDecapConfig config_;

/**
* bpf adapter to interact w/ BPF subsystem
*/
BpfAdapter bpfAdapter_;

/**
* flag which indicates were XdpDecap attached as standalone program or not
*/
bool isStandalone_{true};

/**
* flag which indicate if XdpDecap were loaded into kernel or not
*/
bool isLoaded_{false};

/**
* flag which indicates if XdpDecap were attached
*/
bool isAttached_{false};
};

} // namespace katran
56 changes: 56 additions & 0 deletions katran/decap/XdpDecapStructs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* 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 <string>

namespace katran {

namespace {
std::string kDefaultMapPath = "";
const int kDefaultProgPos = 8;
std::string kDefaultInterface = "lo";
}

/**
* structure which contains main statistics about XDP based decapsulation
* @param uint64_t decap_v4 number of decapsulated ipip packets
* @param uint64_t decap_v6 number of decapsulated ip(4|6)ip6 packets
* @param uint64_t total total number of packets which was processed
*/
struct decap_stats {
uint64_t decap_v4;
uint64_t decap_v6;
uint64_t total;
};

/**
* @param string progPath path to bpf object file w/ xdpdecap program
* @param string mapPath in shared mode - path to bpf prog array
* @param int progPos in shared mode - position in prog array
* @param string interface in standalone mode - interface to attach
*
* structure which contains main XdpDecap configuration
*/
struct XdpDecapConfig {
std::string progPath;
std::string mapPath = kDefaultMapPath;
int progPos = kDefaultProgPos;
std::string interface = kDefaultInterface;
};

}
Loading

0 comments on commit 44546c6

Please sign in to comment.