• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #pragma once
18 
19 #include <linux/if_ether.h>
20 #include <linux/pfkeyv2.h>
21 #include <net/if.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/resource.h>
25 #include <sys/socket.h>
26 #include <sys/utsname.h>
27 
28 #include <string>
29 
30 #include <android-base/unique_fd.h>
31 #include <log/log.h>
32 
33 #include "BpfSyscallWrappers.h"
34 
35 // The buffer size for the buffer that records program loading logs, needs to be large enough for
36 // the largest kernel program.
37 
38 namespace android {
39 namespace bpf {
40 
41 constexpr const int OVERFLOW_COUNTERSET = 2;
42 
43 constexpr const uint64_t NONEXISTENT_COOKIE = 0;
44 
getSocketCookie(int sockFd)45 static inline uint64_t getSocketCookie(int sockFd) {
46     uint64_t sock_cookie;
47     socklen_t cookie_len = sizeof(sock_cookie);
48     int res = getsockopt(sockFd, SOL_SOCKET, SO_COOKIE, &sock_cookie, &cookie_len);
49     if (res < 0) {
50         res = -errno;
51         ALOGE("Failed to get socket cookie: %s\n", strerror(errno));
52         errno = -res;
53         // 0 is an invalid cookie. See sock_gen_cookie.
54         return NONEXISTENT_COOKIE;
55     }
56     return sock_cookie;
57 }
58 
synchronizeKernelRCU()59 static inline int synchronizeKernelRCU() {
60     // This is a temporary hack for network stats map swap on devices running
61     // 4.9 kernels. The kernel code of socket release on pf_key socket will
62     // explicitly call synchronize_rcu() which is exactly what we need.
63     int pfSocket = socket(AF_KEY, SOCK_RAW | SOCK_CLOEXEC, PF_KEY_V2);
64 
65     if (pfSocket < 0) {
66         int ret = -errno;
67         ALOGE("create PF_KEY socket failed: %s", strerror(errno));
68         return ret;
69     }
70 
71     // When closing socket, synchronize_rcu() gets called in sock_release().
72     if (close(pfSocket)) {
73         int ret = -errno;
74         ALOGE("failed to close the PF_KEY socket: %s", strerror(errno));
75         return ret;
76     }
77     return 0;
78 }
79 
setrlimitForTest()80 static inline int setrlimitForTest() {
81     // Set the memory rlimit for the test process if the default MEMLOCK rlimit is not enough.
82     struct rlimit limit = {
83             .rlim_cur = 1073741824,  // 1 GiB
84             .rlim_max = 1073741824,  // 1 GiB
85     };
86     int res = setrlimit(RLIMIT_MEMLOCK, &limit);
87     if (res) {
88         ALOGE("Failed to set the default MEMLOCK rlimit: %s", strerror(errno));
89     }
90     return res;
91 }
92 
93 #define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c))
94 
uncachedKernelVersion()95 static inline unsigned uncachedKernelVersion() {
96     struct utsname buf;
97     int ret = uname(&buf);
98     if (ret) return 0;
99 
100     unsigned kver_major;
101     unsigned kver_minor;
102     unsigned kver_sub;
103     char unused;
104     ret = sscanf(buf.release, "%u.%u.%u%c", &kver_major, &kver_minor, &kver_sub, &unused);
105     // Check the device kernel version
106     if (ret < 3) return 0;
107 
108     return KVER(kver_major, kver_minor, kver_sub);
109 }
110 
kernelVersion()111 static inline unsigned kernelVersion() {
112     static unsigned kver = uncachedKernelVersion();
113     return kver;
114 }
115 
isAtLeastKernelVersion(unsigned major,unsigned minor,unsigned sub)116 static inline bool isAtLeastKernelVersion(unsigned major, unsigned minor, unsigned sub) {
117     return kernelVersion() >= KVER(major, minor, sub);
118 }
119 
120 #define SKIP_IF_BPF_SUPPORTED                              \
121     do {                                                   \
122         if (android::bpf::isAtLeastKernelVersion(4, 9, 0)) \
123             GTEST_SKIP() << "Skip: bpf is supported.";     \
124     } while (0)
125 
126 #define SKIP_IF_BPF_NOT_SUPPORTED                           \
127     do {                                                    \
128         if (!android::bpf::isAtLeastKernelVersion(4, 9, 0)) \
129             GTEST_SKIP() << "Skip: bpf is not supported.";  \
130     } while (0)
131 
132 #define SKIP_IF_EXTENDED_BPF_NOT_SUPPORTED                               \
133     do {                                                                 \
134         if (!android::bpf::isAtLeastKernelVersion(4, 14, 0))             \
135             GTEST_SKIP() << "Skip: extended bpf feature not supported."; \
136     } while (0)
137 
138 #define SKIP_IF_XDP_NOT_SUPPORTED                           \
139     do {                                                    \
140         if (!android::bpf::isAtLeastKernelVersion(5, 9, 0)) \
141             GTEST_SKIP() << "Skip: xdp not supported.";     \
142     } while (0)
143 
144 }  // namespace bpf
145 }  // namespace android
146