Files
android_packages_modules_Co…/service/native/libs/libclat/bpfhelper.cpp
Hungming Chen 07fcf9ca49 ClatCoordinator: use Java class BpfMap to add clat rule
This a preparation to replace duplicated native functions with the
existing Java class.

Bug: 221213090
Test: atest FrameworksNetTests
Test: check map content {iface index, v4addr, v6addr, pfx96} manually.
The map fileds are the same as "ip addr" and clatd logging.

$ adb shell dumpsys netd
ClatdController
  BPF ingress map: iif(iface) nat64Prefix v6Addr -> v4Addr oif(iface)
    47(wlan0) 64:ff9b::/96 2a00:79e1:abc:6f02:f9e1:8c2d:604e:bc06 -> 192.0.0.4 53(v4-wlan0)
  BPF egress map: iif(iface) v4Addr -> v6Addr nat64Prefix oif(iface)
    53(v4-wlan0) 192.0.0.4 -> 2a00:79e1:abc:6f02:f9e1:8c2d:604e:bc06 64:ff9b::/96 47(wlan0) ether

$ adb shell ip addr
47: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ..
53: v4-wlan0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 ..

03-14 18:35:04.822 30852 30852 I clatd   : Starting clat version 1.5 on wlan0 plat=64:ff9b:: v4=192.0.0.4 v6=2a00:79e1:abc:6f02:f9e1:8c2d:604e:bc06

Change-Id: I91d0cb6e76c4ef7bacf91b996786308ff4918f35
2022-03-31 15:53:33 +08:00

167 lines
5.5 KiB
C++

/*
* Copyright 2021 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.
*
* main.c - main function
*/
#define LOG_TAG "bpfhelper"
#include "libclat/bpfhelper.h"
#include <android-base/unique_fd.h>
#include <log/log.h>
#include "bpf/BpfMap.h"
#include "libclat/TcUtils.h"
#define DEVICEPREFIX "v4-"
using android::base::unique_fd;
using android::bpf::BpfMap;
BpfMap<ClatEgress4Key, ClatEgress4Value> mClatEgress4Map;
BpfMap<ClatIngress6Key, ClatIngress6Value> mClatIngress6Map;
namespace android {
namespace net {
namespace clat {
// TODO: have a clearMap function to remove all stubs while system server crash.
// For long term, move bpf access into java and map initialization should live
// ClatCoordinator constructor.
int initMaps(void) {
int rv = getClatEgress4MapFd();
if (rv < 0) {
ALOGE("getClatEgress4MapFd() failure: %s", strerror(-rv));
return -rv;
}
mClatEgress4Map.reset(rv);
rv = getClatIngress6MapFd();
if (rv < 0) {
ALOGE("getClatIngress6MapFd() failure: %s", strerror(-rv));
mClatEgress4Map.reset(-1);
return -rv;
}
mClatIngress6Map.reset(rv);
return 0;
}
void maybeStartBpf(const ClatdTracker& tracker) {
auto isEthernet = android::net::isEthernet(tracker.iface);
if (!isEthernet.ok()) {
ALOGE("isEthernet(%s[%d]) failure: %s", tracker.iface, tracker.ifIndex,
isEthernet.error().message().c_str());
return;
}
// This program will be attached to the v4-* interface which is a TUN and thus always rawip.
int rv = getClatEgress4ProgFd(RAWIP);
if (rv < 0) {
ALOGE("getClatEgress4ProgFd(RAWIP) failure: %s", strerror(-rv));
return;
}
unique_fd txRawIpProgFd(rv);
rv = getClatIngress6ProgFd(isEthernet.value());
if (rv < 0) {
ALOGE("getClatIngress6ProgFd(%d) failure: %s", isEthernet.value(), strerror(-rv));
return;
}
unique_fd rxProgFd(rv);
// We do tc setup *after* populating the maps, so scanning through them
// can always be used to tell us what needs cleanup.
// Usually the clsact will be added in RouteController::addInterfaceToPhysicalNetwork.
// But clat is started before the v4- interface is added to the network. The clat startup have
// to add clsact of v4- tun interface first for adding bpf filter in maybeStartBpf.
// TODO: move "qdisc add clsact" of v4- tun interface out from ClatdController.
rv = tcQdiscAddDevClsact(tracker.v4ifIndex);
if (rv) {
ALOGE("tcQdiscAddDevClsact(%d[%s]) failure: %s", tracker.v4ifIndex, tracker.v4iface,
strerror(-rv));
return;
}
rv = tcFilterAddDevEgressClatIpv4(tracker.v4ifIndex, txRawIpProgFd, RAWIP);
if (rv) {
ALOGE("tcFilterAddDevEgressClatIpv4(%d[%s], RAWIP) failure: %s", tracker.v4ifIndex,
tracker.v4iface, strerror(-rv));
// The v4- interface clsact is not deleted for unwinding error because once it is created
// with interface addition, the lifetime is till interface deletion. Moreover, the clsact
// has no clat filter now. It should not break anything.
return;
}
rv = tcFilterAddDevIngressClatIpv6(tracker.ifIndex, rxProgFd, isEthernet.value());
if (rv) {
ALOGE("tcFilterAddDevIngressClatIpv6(%d[%s], %d) failure: %s", tracker.ifIndex,
tracker.iface, isEthernet.value(), strerror(-rv));
rv = tcFilterDelDevEgressClatIpv4(tracker.v4ifIndex);
if (rv) {
ALOGE("tcFilterDelDevEgressClatIpv4(%d[%s]) failure: %s", tracker.v4ifIndex,
tracker.v4iface, strerror(-rv));
}
// The v4- interface clsact is not deleted. See the reason in the error unwinding code of
// the egress filter attaching of v4- tun interface.
return;
}
// success
}
void maybeStopBpf(const ClatdTracker& tracker) {
int rv = tcFilterDelDevIngressClatIpv6(tracker.ifIndex);
if (rv < 0) {
ALOGE("tcFilterDelDevIngressClatIpv6(%d[%s]) failure: %s", tracker.ifIndex, tracker.iface,
strerror(-rv));
}
rv = tcFilterDelDevEgressClatIpv4(tracker.v4ifIndex);
if (rv < 0) {
ALOGE("tcFilterDelDevEgressClatIpv4(%d[%s]) failure: %s", tracker.v4ifIndex,
tracker.v4iface, strerror(-rv));
}
// We cleanup the maps last, so scanning through them can be used to
// determine what still needs cleanup.
ClatEgress4Key txKey = {
.iif = tracker.v4ifIndex,
.local4 = tracker.v4,
};
auto ret = mClatEgress4Map.deleteValue(txKey);
if (!ret.ok()) ALOGE("mClatEgress4Map.deleteValue failure: %s", strerror(ret.error().code()));
ClatIngress6Key rxKey = {
.iif = tracker.ifIndex,
.pfx96 = tracker.pfx96,
.local6 = tracker.v6,
};
ret = mClatIngress6Map.deleteValue(rxKey);
if (!ret.ok()) ALOGE("mClatIngress6Map.deleteValue failure: %s", strerror(ret.error().code()));
}
} // namespace clat
} // namespace net
} // namespace android