blob: f663154f31e0ef23e86a2ec608c9a0419eb34284 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <error.h>
#include <linux/bpf.h>
#include <linux/unistd.h>
#include <net/if.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <netdutils/Misc.h>
#include "BpfProgSets.h"
#include "bpf/BpfUtils.h"
using android::base::unique_fd;
namespace android {
namespace bpf {
int loadAndAttachProgram(bpf_attach_type type, const char* path, const char* name,
const unique_fd& cookieTagMap, const unique_fd& uidCounterSetMap,
const unique_fd& uidStatsMap, const unique_fd& tagStatsMap) {
unique_fd cg_fd(open(CGROUP_ROOT_PATH, O_DIRECTORY | O_RDONLY | O_CLOEXEC));
if (cg_fd < 0) {
perror("Failed to open the cgroup directory");
return -1;
}
unique_fd fd;
if (type == BPF_CGROUP_INET_EGRESS) {
fd.reset(loadEgressProg(cookieTagMap.get(), uidStatsMap.get(), tagStatsMap.get(),
uidCounterSetMap.get()));
} else {
fd.reset(loadIngressProg(cookieTagMap.get(), uidStatsMap.get(), tagStatsMap.get(),
uidCounterSetMap.get()));
}
if (fd < 0) {
fprintf(stderr, "load %s failed: %s", name, strerror(errno));
return -1;
}
int ret = attachProgram(type, fd, cg_fd);
if (ret) {
fprintf(stderr, "%s attach failed: %s", name, strerror(errno));
return -1;
}
ret = mapPin(fd, path);
if (ret) {
fprintf(stderr, "Pin %s as file %s failed: %s", name, path, strerror(errno));
return -1;
}
return 0;
}
} // namespace bpf
} // namespace android
using android::bpf::BPF_EGRESS_PROG_PATH;
using android::bpf::BPF_INGRESS_PROG_PATH;
using android::bpf::COOKIE_UID_MAP_PATH;
using android::bpf::TAG_STATS_MAP_PATH;
using android::bpf::UID_COUNTERSET_MAP_PATH;
using android::bpf::UID_STATS_MAP_PATH;
static void usage(void) {
fprintf(stderr,
"Usage: ./bpfloader [-i] [-e]\n"
" -i load ingress bpf program\n"
" -e load egress bpf program\n");
}
int main(int argc, char** argv) {
int ret = 0;
unique_fd cookieTagMap(android::bpf::mapRetrieve(COOKIE_UID_MAP_PATH, 0));
if (cookieTagMap < 0) {
perror("Failed to get cookieTagMap");
exit(-1);
}
unique_fd uidCounterSetMap(android::bpf::mapRetrieve(UID_COUNTERSET_MAP_PATH, 0));
if (uidCounterSetMap < 0) {
perror("Failed to get uidCounterSetMap");
exit(-1);
}
unique_fd uidStatsMap(android::bpf::mapRetrieve(UID_STATS_MAP_PATH, 0));
if (uidStatsMap < 0) {
perror("Failed to get uidStatsMap");
exit(-1);
}
unique_fd tagStatsMap(android::bpf::mapRetrieve(TAG_STATS_MAP_PATH, 0));
if (tagStatsMap < 0) {
perror("Failed to get tagStatsMap");
exit(-1);
}
int opt;
bool doIngress = false, doEgress = false;
while ((opt = getopt(argc, argv, "ie")) != -1) {
switch (opt) {
case 'i':
doIngress = true;
break;
case 'e':
doEgress = true;
break;
default:
fprintf(stderr, "unknown argument %c", opt);
usage();
exit(-1);
}
}
if (doIngress) {
ret = android::bpf::loadAndAttachProgram(BPF_CGROUP_INET_INGRESS, BPF_INGRESS_PROG_PATH,
"ingress_prog", cookieTagMap, uidCounterSetMap,
uidStatsMap, tagStatsMap);
if (ret) {
fprintf(stderr, "Failed to set up ingress program");
return ret;
}
}
if (doEgress) {
ret = android::bpf::loadAndAttachProgram(BPF_CGROUP_INET_EGRESS, BPF_EGRESS_PROG_PATH,
"egress_prog", cookieTagMap, uidCounterSetMap,
uidStatsMap, tagStatsMap);
if (ret) {
fprintf(stderr, "Failed to set up ingress program");
return ret;
}
}
return ret;
}