example_grpc/katran_server.cpp (104 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. */ #include <signal.h> #include <iostream> #include <memory> #include <string> #include <thread> #include <vector> #include <folly/Conv.h> #include <folly/String.h> #include <folly/init/Init.h> #include <folly/io/async/EventBase.h> #include <gflags/gflags.h> #include <grpc++/grpc++.h> #include "GrpcSignalHandler.h" #include "KatranGrpcService.h" #include "katran/lib/MacHelpers.h" using grpc::Server; using grpc::ServerBuilder; DEFINE_string(server, "0.0.0.0:50051", "Service server:port"); DEFINE_string(intf, "eth0", "main interface"); DEFINE_string(hc_intf, "", "interface for healthchecking"); DEFINE_string(ipip_intf, "ipip0", "ipip (v4) encap interface"); DEFINE_string(ipip6_intf, "ipip60", "ip(6)ip6 (v6) encap interface"); DEFINE_string(balancer_prog, "./balancer_kern.o", "path to balancer bpf prog"); DEFINE_string( healthchecker_prog, "./healthchecking_ipip.o", "path to healthchecking bpf prog"); DEFINE_string( default_mac, "00:00:00:00:00:01", "mac address of default router. must be in fomrat: xx:xx:xx:xx:xx:xx"); DEFINE_int32(priority, 2307, "tc's priority for bpf progs"); DEFINE_string( map_path, "", "path to pinned map from root xdp prog." " default path forces to work in standalone mode"); DEFINE_int32(prog_pos, 2, "katran's position inside root xdp array"); DEFINE_bool(hc_forwarding, true, "turn on forwarding path for healthchecks"); DEFINE_int32(shutdown_delay, 10000, "shutdown delay in milliseconds"); DEFINE_int64(lru_size, 8000000, "size of LRU table"); DEFINE_string(forwarding_cores, "", "coma separed list of forwarding cores"); DEFINE_string( numa_nodes, "", "coma separed list of numa nodes to forwarding cores mapping"); // routine which parses coma separated string of numbers // (e.g. "1,2,3,4,10,11,12,13") to vector of int32_t // will throw on failure. std::vector<int32_t> parseIntLine(const std::string& line) { std::vector<int32_t> nums; if (!line.empty()) { std::vector<std::string> splitedLine; folly::split(",", line, splitedLine); for (const auto& num_str : splitedLine) { auto num = folly::to<int32_t>(num_str); nums.push_back(num); } } return nums; } void RunServer( katran::KatranConfig& config, int32_t delay, std::shared_ptr<folly::EventBase> evb) { std::string server_address(FLAGS_server); lb::katran::KatranGrpcService service(config); ServerBuilder builder; // Listen on the given address without any authentication mechanism. builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); // Register "service" as the instance through which we'll communicate with // clients. In this case it corresponds to an *synchronous* service. builder.RegisterService(&service); // Finally assemble the server. std::unique_ptr<Server> server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; lb::katran::GrpcSignalHandler grpcSigHandler(evb, server.get(), delay); grpcSigHandler.registerSignalHandler(SIGINT); grpcSigHandler.registerSignalHandler(SIGTERM); // Wait for the server to shutdown. Note that some other thread must be // responsible for shutting down the server for this call to ever return. server->Wait(); } int main(int argc, char** argv) { folly::init(&argc, &argv); FLAGS_logtostderr = 1; auto forwardingCores = parseIntLine(FLAGS_forwarding_cores); VLOG(2) << "size of forwarding cores vector is " << forwardingCores.size(); auto numaNodes = parseIntLine(FLAGS_numa_nodes); VLOG(2) << "size of numa nodes vector is " << numaNodes.size(); katran::KatranConfig config = { .mainInterface = FLAGS_intf, .v4TunInterface = FLAGS_ipip_intf, .v6TunInterface = FLAGS_ipip6_intf, .balancerProgPath = FLAGS_balancer_prog, .healthcheckingProgPath = FLAGS_healthchecker_prog, .defaultMac = katran::convertMacToUint(FLAGS_default_mac), .priority = static_cast<uint32_t>(FLAGS_priority), .rootMapPath = FLAGS_map_path, .rootMapPos = static_cast<uint32_t>(FLAGS_prog_pos), .enableHc = FLAGS_hc_forwarding, }; config.LruSize = static_cast<uint64_t>(FLAGS_lru_size); config.forwardingCores = forwardingCores; config.numaNodes = numaNodes; config.hcInterface = FLAGS_hc_intf; config.hashFunction = katran::HashFunction::MaglevV2; auto evb = std::make_shared<folly::EventBase>(); std::thread t1([evb]() { evb->loopForever(); }); t1.detach(); RunServer(config, FLAGS_shutdown_delay, evb); return 0; }