blob: 0a2be51fc20a6cd24ae778d8c67bba9a64b72ef1 [file] [log] [blame]
Patrick Rohr27846ff2022-01-17 12:22:51 +01001/*
2 * Copyright 2022 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 * TcUtilsTest.cpp - unit tests for TcUtils.cpp
17 */
18
19#include <gtest/gtest.h>
20
Patrick Rohr1f7ba252022-01-17 16:14:10 +010021#include "kernelversion.h"
Patrick Rohr27846ff2022-01-17 12:22:51 +010022#include <tcutils/tcutils.h>
23
Patrick Rohr1f7ba252022-01-17 16:14:10 +010024#include <BpfSyscallWrappers.h>
Patrick Rohr27846ff2022-01-17 12:22:51 +010025#include <errno.h>
Patrick Rohr1f7ba252022-01-17 16:14:10 +010026#include <linux/if_ether.h>
Patrick Rohr27846ff2022-01-17 12:22:51 +010027
28namespace android {
29
30TEST(LibTcUtilsTest, IsEthernetOfNonExistingIf) {
31 bool result = false;
32 int error = isEthernet("not_existing_if", result);
33 ASSERT_FALSE(result);
34 ASSERT_EQ(-ENODEV, error);
35}
36
37TEST(LibTcUtilsTest, IsEthernetOfLoopback) {
38 bool result = false;
39 int error = isEthernet("lo", result);
40 ASSERT_FALSE(result);
41 ASSERT_EQ(-EAFNOSUPPORT, error);
42}
43
44// If wireless 'wlan0' interface exists it should be Ethernet.
45// See also HardwareAddressTypeOfWireless.
46TEST(LibTcUtilsTest, IsEthernetOfWireless) {
47 bool result = false;
48 int error = isEthernet("wlan0", result);
49 if (!result && error == -ENODEV)
50 return;
51
52 ASSERT_EQ(0, error);
53 ASSERT_TRUE(result);
54}
55
56// If cellular 'rmnet_data0' interface exists it should
57// *probably* not be Ethernet and instead be RawIp.
58// See also HardwareAddressTypeOfCellular.
59TEST(LibTcUtilsTest, IsEthernetOfCellular) {
60 bool result = false;
61 int error = isEthernet("rmnet_data0", result);
62 if (!result && error == -ENODEV)
63 return;
64
65 ASSERT_EQ(0, error);
66 ASSERT_FALSE(result);
67}
68
Patrick Rohr42b58ae2022-01-17 13:09:12 +010069// See Linux kernel source in include/net/flow.h
70static constexpr int LOOPBACK_IFINDEX = 1;
71
72TEST(LibTcUtilsTest, AttachReplaceDetachClsactLo) {
73 // This attaches and detaches a configuration-less and thus no-op clsact
74 // qdisc to loopback interface (and it takes fractions of a second)
75 EXPECT_EQ(0, tcAddQdiscClsact(LOOPBACK_IFINDEX));
76 EXPECT_EQ(0, tcReplaceQdiscClsact(LOOPBACK_IFINDEX));
77 EXPECT_EQ(0, tcDeleteQdiscClsact(LOOPBACK_IFINDEX));
78 EXPECT_EQ(-EINVAL, tcDeleteQdiscClsact(LOOPBACK_IFINDEX));
79}
80
Patrick Rohr1f7ba252022-01-17 16:14:10 +010081TEST(LibTcUtilsTest, AddAndDeleteBpfFilter) {
82 // TODO: this should use bpf_shared.h rather than hardcoding the path
83 static constexpr char bpfProgPath[] =
84 "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream6_ether";
85 const int errNOENT = isAtLeastKernelVersion(4, 19, 0) ? ENOENT : EINVAL;
86
87 // static test values
88 static constexpr bool ingress = true;
89 static constexpr uint16_t prio = 17;
90 static constexpr uint16_t proto = ETH_P_ALL;
91
92 // try to delete missing filter from missing qdisc
93 EXPECT_EQ(-EINVAL, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
94 // try to attach bpf filter to missing qdisc
95 EXPECT_EQ(-EINVAL, tcAddBpfFilter(LOOPBACK_IFINDEX, ingress, prio, proto,
96 bpfProgPath));
97 // add the clsact qdisc
98 EXPECT_EQ(0, tcAddQdiscClsact(LOOPBACK_IFINDEX));
99 // try to delete missing filter when there is a qdisc attached
100 EXPECT_EQ(-errNOENT, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
101 // add and delete a bpf filter
102 EXPECT_EQ(
103 0, tcAddBpfFilter(LOOPBACK_IFINDEX, ingress, prio, proto, bpfProgPath));
104 EXPECT_EQ(0, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
105 // try to remove the same filter a second time
106 EXPECT_EQ(-errNOENT, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
107 // remove the clsact qdisc
108 EXPECT_EQ(0, tcDeleteQdiscClsact(LOOPBACK_IFINDEX));
109 // once again, try to delete missing filter from missing qdisc
110 EXPECT_EQ(-EINVAL, tcDeleteFilter(LOOPBACK_IFINDEX, ingress, prio, proto));
111}
112
Patrick Rohr27846ff2022-01-17 12:22:51 +0100113} // namespace android