Android bw_costly_<iface>链

测试时关注到bw_costly_链

因为和iface有关。猜测这个链是动态生成的。

开关数据业务测试,果然关闭数据业务后,bw_OUTPUT中不再会调用bw_costly_rmnet_data3,也没有bw_costly_rmnet_data3这个链了。

再次打开数据业务后出现了bw_costly_rmnet_data2。说明上次上网的rmnet_data3口,这此上网的rmnet_data2。

cpp 复制代码
:/ # iptables -t filter -nvL bw_OUTPUT
Chain bw_OUTPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination
   24  1909 bw_global_alert  all  --  *      *       0.0.0.0/0            0.0.0.0/0
    2   120 bw_costly_rmnet_data3  all  --  *      rmnet_data3  0.0.0.0/0            0.0.0.0/0

是netd模块自己检测上网状态后,自己添加的吗?

查看代码是netd的BandwidthController生成。

cpp 复制代码
int BandwidthController::setInterfaceQuota(const std::string& iface, int64_t maxBytes) {
    const std::string& cost = iface;
....
    /* Insert ingress quota. */
    auto it = mQuotaIfaces.find(iface);

    if (it != mQuotaIfaces.end()) {
        if (int res = updateQuota(cost, maxBytes)) {
            ALOGE("Failed update quota for %s", iface.c_str());
            removeInterfaceQuota(iface);
            return res;
        }
        it->second.quota = maxBytes;
        return 0;
    }

    const std::string chain = "bw_costly_" + iface;
    const int ruleInsertPos = (mGlobalAlertBytes) ? 2 : 1;
    std::vector<std::string> cmds = {
            "*filter",
            StringPrintf(":%s -", chain.c_str()),
            StringPrintf("-A %s -j bw_penalty_box", chain.c_str()),
            StringPrintf("-I bw_INPUT %d -i %s -j %s", ruleInsertPos, iface.c_str(), chain.c_str()),
            StringPrintf("-I bw_OUTPUT %d -o %s -j %s", ruleInsertPos, iface.c_str(),
                         chain.c_str()),
            StringPrintf("-A bw_FORWARD -i %s -j %s", iface.c_str(), chain.c_str()),
            StringPrintf("-A bw_FORWARD -o %s -j %s", iface.c_str(), chain.c_str()),
            StringPrintf("-A %s -m quota2 ! --quota %" PRId64 " --name %s -j REJECT", chain.c_str(),
                         maxBytes, cost.c_str()),
            "COMMIT\n",
    };
    if (iptablesRestoreFunction(V4V6, Join(cmds, "\n"), nullptr) != 0) {
        ALOGE("Failed set quota rule");
        removeInterfaceQuota(iface);
        return -EREMOTEIO;
    }

    mQuotaIfaces[iface] = QuotaInfo{maxBytes, 0};
    return 0;
}

netd 向上提供此接口,内部除了ndc模块通过控制台可以调用,没有自动关注网络状态,调用setInterfaceQuota的地方:

cpp 复制代码
binder::Status NetdNativeService::bandwidthSetInterfaceQuota(const std::string& ifName,
                                                             int64_t bytes) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->bandwidthCtrl.setInterfaceQuota(ifName, bytes);
    return statusFromErrcode(res);
}

继续在android代码中搜索:

framework的NetworkManagementService.java中调用

mNetdService.bandwidthSetInterfaceQuota

cpp 复制代码
    public void setInterfaceQuota(String iface, long quotaBytes) {
        NetworkStack.checkNetworkStackPermission(mContext);

        synchronized (mQuotaLock) {
            if (mActiveQuotas.containsKey(iface)) {
                throw new IllegalStateException("iface " + iface + " already has quota");
            }

            try {
                // TODO: support quota shared across interfaces
                mNetdService.bandwidthSetInterfaceQuota(iface, quotaBytes);

                mActiveQuotas.put(iface, quotaBytes);
            } catch (RemoteException | ServiceSpecificException e) {
                throw new IllegalStateException(e);
            }

            synchronized (mTetheringStatsProviders) {
                for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
                    try {
                        provider.setInterfaceQuota(iface, quotaBytes);
                    } catch (RemoteException e) {
                        Log.e(TAG, "Problem setting tethering data limit on provider " +
                                mTetheringStatsProviders.get(provider) + ": " + e);
                    }
                }
            }
        }
    }

调用序列是:
NatworkManagementService:

NatworkManagementService.systemReady->prepareNativeDaemon()->setInterfaceQuota->mNetdService.bandwidthSetInterfaceQuota

下一步分析数据业务开关后,是什么流程触发NatworkManagementService的setInterfaceQuota和removeInterfaceQuota的调用。

参考链接:

Android系统中iptables的应用(二)BandwidthController https://blog.csdn.net/xiaokeweng/article/details/48810049

相关推荐
teacher伟大光荣且正确1 小时前
Qt Creator 配置 Android 编译环境
android·开发语言·qt
飞猿_SIR4 小时前
Android Exoplayer 实现多个音视频文件混合播放以及音轨切换
android·音视频
HumoChen994 小时前
GZip+Base64压缩字符串在ios上解压报错问题解决(安卓、PC模拟器正常)
android·小程序·uniapp·base64·gzip
沙振宇8 小时前
【HarmonyOS】ArkTS开发应用的横竖屏切换
android·华为·harmonyos
橙子1991101610 小时前
Kotlin 中的作用域函数
android·开发语言·kotlin
zimoyin10 小时前
Kotlin 懒初始化值
android·开发语言·kotlin
枣伊吕波11 小时前
第六节第二部分:抽象类的应用-模板方法设计模式
android·java·设计模式
萧然CS11 小时前
使用ADB命令操作Android的apk/aab包
android·adb
_extraordinary_15 小时前
MySQL 事务(二)
android·数据库·mysql
鸿蒙布道师19 小时前
鸿蒙NEXT开发动画案例5
android·ios·华为·harmonyos·鸿蒙系统·arkui·huawei