summaryrefslogtreecommitdiff
path: root/server/OffloadUtils.h
blob: 818fd39de876b0c832768784f747f19ffeb75315 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * Copyright (C) 2019 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.
 */

#pragma once

#include <android-base/result.h>
#include <errno.h>
#include <linux/if_ether.h>
#include <linux/rtnetlink.h>

#include <string>

#include "bpf/BpfUtils.h"
#include "netdbpf/bpf_shared.h"

namespace android {
namespace net {

// For better code clarity - do not change values - used for booleans like
// with_ethernet_header or isEthernet.
constexpr bool RAWIP = false;
constexpr bool ETHER = true;

// For better code clarity when used for 'bool ingress' parameter.
constexpr bool EGRESS = false;
constexpr bool INGRESS = true;

// The priority of clat/tether hooks - smaller is higher priority.
constexpr uint16_t PRIO_CLAT = 1;
constexpr uint16_t PRIO_TETHER = 2;

// this returns an ARPHRD_* constant or a -errno
int hardwareAddressType(const std::string& interface);

base::Result<bool> isEthernet(const std::string& interface);

inline int getClatEgressMapFd(void) {
    const int fd = bpf::mapRetrieveRW(CLAT_EGRESS_MAP_PATH);
    return (fd == -1) ? -errno : fd;
}

inline int getClatEgressProgFd(bool with_ethernet_header) {
    const int fd = bpf::retrieveProgram(with_ethernet_header ? CLAT_EGRESS_PROG_ETHER_PATH
                                                             : CLAT_EGRESS_PROG_RAWIP_PATH);
    return (fd == -1) ? -errno : fd;
}

inline int getClatIngressMapFd(void) {
    const int fd = bpf::mapRetrieveRW(CLAT_INGRESS_MAP_PATH);
    return (fd == -1) ? -errno : fd;
}

inline int getClatIngressProgFd(bool with_ethernet_header) {
    const int fd = bpf::retrieveProgram(with_ethernet_header ? CLAT_INGRESS_PROG_ETHER_PATH
                                                             : CLAT_INGRESS_PROG_RAWIP_PATH);
    return (fd == -1) ? -errno : fd;
}

inline int getTetherIngressMapFd(void) {
    const int fd = bpf::mapRetrieveRW(TETHER_INGRESS_MAP_PATH);
    return (fd == -1) ? -errno : fd;
}

inline int getTetherIngressProgFd(bool with_ethernet_header) {
    const int fd = bpf::retrieveProgram(with_ethernet_header ? TETHER_INGRESS_PROG_ETHER_PATH
                                                             : TETHER_INGRESS_PROG_RAWIP_PATH);
    return (fd == -1) ? -errno : fd;
}

inline int getTetherStatsMapFd(void) {
    const int fd = bpf::mapRetrieveRW(TETHER_STATS_MAP_PATH);
    return (fd == -1) ? -errno : fd;
}

inline int getTetherLimitMapFd(void) {
    const int fd = bpf::mapRetrieveRW(TETHER_LIMIT_MAP_PATH);
    return (fd == -1) ? -errno : fd;
}

int doTcQdiscClsact(int ifIndex, uint16_t nlMsgType, uint16_t nlMsgFlags);

inline int tcQdiscAddDevClsact(int ifIndex) {
    return doTcQdiscClsact(ifIndex, RTM_NEWQDISC, NLM_F_EXCL | NLM_F_CREATE);
}

inline int tcQdiscReplaceDevClsact(int ifIndex) {
    return doTcQdiscClsact(ifIndex, RTM_NEWQDISC, NLM_F_CREATE | NLM_F_REPLACE);
}

inline int tcQdiscDelDevClsact(int ifIndex) {
    return doTcQdiscClsact(ifIndex, RTM_DELQDISC, 0);
}

// tc filter add dev .. in/egress prio 1 protocol ipv6/ip bpf object-pinned /sys/fs/bpf/...
// direct-action
int tcFilterAddDevBpf(int ifIndex, bool ingress, uint16_t prio, uint16_t proto, int bpfFd,
                      bool ethernet);

// tc filter add dev .. ingress prio 1 protocol ipv6 bpf object-pinned /sys/fs/bpf/... direct-action
inline int tcFilterAddDevIngressClatIpv6(int ifIndex, int bpfFd, bool ethernet) {
    return tcFilterAddDevBpf(ifIndex, INGRESS, PRIO_CLAT, ETH_P_IPV6, bpfFd, ethernet);
}

// tc filter add dev .. egress prio 1 protocol ip bpf object-pinned /sys/fs/bpf/... direct-action
inline int tcFilterAddDevEgressClatIpv4(int ifIndex, int bpfFd, bool ethernet) {
    return tcFilterAddDevBpf(ifIndex, EGRESS, PRIO_CLAT, ETH_P_IP, bpfFd, ethernet);
}

// tc filter add dev .. ingress prio 2 protocol ipv6 bpf object-pinned /sys/fs/bpf/... direct-action
inline int tcFilterAddDevIngressTether(int ifIndex, int bpfFd, bool ethernet) {
    return tcFilterAddDevBpf(ifIndex, INGRESS, PRIO_TETHER, ETH_P_IPV6, bpfFd, ethernet);
}

// tc filter del dev .. in/egress prio .. protocol ..
int tcFilterDelDev(int ifIndex, bool ingress, uint16_t prio, uint16_t proto);

// tc filter del dev .. ingress prio 1 protocol ipv6
inline int tcFilterDelDevIngressClatIpv6(int ifIndex) {
    return tcFilterDelDev(ifIndex, INGRESS, PRIO_CLAT, ETH_P_IPV6);
}

// tc filter del dev .. egress prio 1 protocol ip
inline int tcFilterDelDevEgressClatIpv4(int ifIndex) {
    return tcFilterDelDev(ifIndex, EGRESS, PRIO_CLAT, ETH_P_IP);
}

// tc filter del dev .. ingress prio 2 protocol ipv6
inline int tcFilterDelDevIngressTether(int ifIndex) {
    return tcFilterDelDev(ifIndex, INGRESS, PRIO_TETHER, ETH_P_IPV6);
}

}  // namespace net
}  // namespace android