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

相关推荐
GEEKVIP2 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
model20054 小时前
android + tflite 分类APP开发-2
android·分类·tflite
彭于晏6894 小时前
Android广播
android·java·开发语言
与衫5 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql
500了11 小时前
Kotlin基本知识
android·开发语言·kotlin
人工智能的苟富贵12 小时前
Android Debug Bridge(ADB)完全指南
android·adb
小雨cc5566ru17 小时前
uniapp+Android面向网络学习的时间管理工具软件 微信小程序
android·微信小程序·uni-app
bianshaopeng18 小时前
android 原生加载pdf
android·pdf
hhzz18 小时前
Linux Shell编程快速入门以及案例(Linux一键批量启动、停止、重启Jar包Shell脚本)
android·linux·jar
火红的小辣椒19 小时前
XSS基础
android·web安全