blob: f663154f31e0ef23e86a2ec608c9a0419eb34284 [file] [log] [blame]
Chenbo Feng05393d82018-01-09 15:18:43 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <error.h>
18#include <linux/bpf.h>
19#include <linux/unistd.h>
20#include <net/if.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <android-base/stringprintf.h>
26#include <android-base/unique_fd.h>
27
28#include <netdutils/Misc.h>
29#include "BpfProgSets.h"
30#include "bpf/BpfUtils.h"
31
32using android::base::unique_fd;
33
34namespace android {
35namespace bpf {
36
37int loadAndAttachProgram(bpf_attach_type type, const char* path, const char* name,
38 const unique_fd& cookieTagMap, const unique_fd& uidCounterSetMap,
39 const unique_fd& uidStatsMap, const unique_fd& tagStatsMap) {
40 unique_fd cg_fd(open(CGROUP_ROOT_PATH, O_DIRECTORY | O_RDONLY | O_CLOEXEC));
41 if (cg_fd < 0) {
42 perror("Failed to open the cgroup directory");
43 return -1;
44 }
45
46 unique_fd fd;
47 if (type == BPF_CGROUP_INET_EGRESS) {
48 fd.reset(loadEgressProg(cookieTagMap.get(), uidStatsMap.get(), tagStatsMap.get(),
49 uidCounterSetMap.get()));
50 } else {
51 fd.reset(loadIngressProg(cookieTagMap.get(), uidStatsMap.get(), tagStatsMap.get(),
52 uidCounterSetMap.get()));
53 }
54
55 if (fd < 0) {
56 fprintf(stderr, "load %s failed: %s", name, strerror(errno));
57 return -1;
58 }
59
60 int ret = attachProgram(type, fd, cg_fd);
61 if (ret) {
62 fprintf(stderr, "%s attach failed: %s", name, strerror(errno));
63 return -1;
64 }
65
66 ret = mapPin(fd, path);
67 if (ret) {
68 fprintf(stderr, "Pin %s as file %s failed: %s", name, path, strerror(errno));
69 return -1;
70 }
71 return 0;
72}
73
74} // namespace bpf
75} // namespace android
76
77using android::bpf::BPF_EGRESS_PROG_PATH;
78using android::bpf::BPF_INGRESS_PROG_PATH;
79using android::bpf::COOKIE_UID_MAP_PATH;
80using android::bpf::TAG_STATS_MAP_PATH;
81using android::bpf::UID_COUNTERSET_MAP_PATH;
82using android::bpf::UID_STATS_MAP_PATH;
83
84static void usage(void) {
85 fprintf(stderr,
86 "Usage: ./bpfloader [-i] [-e]\n"
87 " -i load ingress bpf program\n"
88 " -e load egress bpf program\n");
89}
90
91int main(int argc, char** argv) {
92 int ret = 0;
93 unique_fd cookieTagMap(android::bpf::mapRetrieve(COOKIE_UID_MAP_PATH, 0));
94 if (cookieTagMap < 0) {
95 perror("Failed to get cookieTagMap");
96 exit(-1);
97 }
98
99 unique_fd uidCounterSetMap(android::bpf::mapRetrieve(UID_COUNTERSET_MAP_PATH, 0));
100 if (uidCounterSetMap < 0) {
101 perror("Failed to get uidCounterSetMap");
102 exit(-1);
103 }
104
105 unique_fd uidStatsMap(android::bpf::mapRetrieve(UID_STATS_MAP_PATH, 0));
106 if (uidStatsMap < 0) {
107 perror("Failed to get uidStatsMap");
108 exit(-1);
109 }
110
111 unique_fd tagStatsMap(android::bpf::mapRetrieve(TAG_STATS_MAP_PATH, 0));
112 if (tagStatsMap < 0) {
113 perror("Failed to get tagStatsMap");
114 exit(-1);
115 }
116 int opt;
117 bool doIngress = false, doEgress = false;
118 while ((opt = getopt(argc, argv, "ie")) != -1) {
119 switch (opt) {
120 case 'i':
121 doIngress = true;
122 break;
123 case 'e':
124 doEgress = true;
125 break;
126 default:
127 fprintf(stderr, "unknown argument %c", opt);
128 usage();
129 exit(-1);
130 }
131 }
132 if (doIngress) {
133 ret = android::bpf::loadAndAttachProgram(BPF_CGROUP_INET_INGRESS, BPF_INGRESS_PROG_PATH,
134 "ingress_prog", cookieTagMap, uidCounterSetMap,
135 uidStatsMap, tagStatsMap);
136 if (ret) {
137 fprintf(stderr, "Failed to set up ingress program");
138 return ret;
139 }
140 }
141 if (doEgress) {
142 ret = android::bpf::loadAndAttachProgram(BPF_CGROUP_INET_EGRESS, BPF_EGRESS_PROG_PATH,
143 "egress_prog", cookieTagMap, uidCounterSetMap,
144 uidStatsMap, tagStatsMap);
145 if (ret) {
146 fprintf(stderr, "Failed to set up ingress program");
147 return ret;
148 }
149 }
150 return ret;
151}