android内核cmdline中给以太网设置了静态ip,
每次android重启的时候,刚开始用电脑能ping通以太网ip,ping通持续大概10秒,然后ping不通了。
跟了以下代码,发现在netd模块中,RouteController.cpp文件里注释掉两个函数(flushRules,addUnreachableRule)的执行,就能一直ping通,不明白这两个函数具体怎么影响了ping,所以不知道怎么解决这个ping问题。
int RouteController::Init(unsigned localNetId) {
/*if (int ret = flushRules()) {
return ret;
}*/
if (int ret = addLegacyRouteRules()) {
return ret;
}
if (int ret = addLocalNetworkRules(localNetId)) {
return ret;
}
/*if (int ret = addUnreachableRule()) {
return ret;
}*/
// Don't complain if we can't add the dummy network, since not all devices support it.
configureDummyNetwork();
updateTableNamesFile();
return 0;
}
WARN_UNUSED_RESULT int flushRules() {
NetlinkDumpFilter shouldDelete = [] (nlmsghdr *nlh) {
// Don't touch rules at priority 0 because by default they are used for local input.
return getRulePriority(nlh) != 0;
};
return rtNetlinkFlush(RTM_GETRULE, RTM_DELRULE, "rules", shouldDelete);
}
// Add an explicit unreachable rule close to the end of the prioriy list to make it clear that
// relying on the kernel-default "from all lookup main" rule at priority 32766 is not intended
// behaviour. We do flush the kernel-default rules at startup, but having an explicit unreachable
// rule will hopefully make things even clearer.
WARN_UNUSED_RESULT int addUnreachableRule() {
return modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_UNREACHABLE, FR_ACT_UNREACHABLE, RT_TABLE_UNSPEC,
MARK_UNSET, MARK_UNSET, IIF_NONE, OIF_NONE, INVALID_UID, INVALID_UID);
}
// Adds or removes a routing rule for IPv4 and IPv6.
//
// + If |table| is non-zero, the rule points at the specified routing table. Otherwise, the table is
// unspecified. An unspecified table is not allowed when creating an FR_ACT_TO_TBL rule.
// + If |mask| is non-zero, the rule matches the specified fwmark and mask. Otherwise, |fwmark| is
// ignored.
// + If |iif| is non-NULL, the rule matches the specified incoming interface.
// + If |oif| is non-NULL, the rule matches the specified outgoing interface.
// + If |uidStart| and |uidEnd| are not INVALID_UID, the rule matches packets from UIDs in that
// range (inclusive). Otherwise, the rule matches packets from all UIDs.
//
// Returns 0 on success or negative errno on failure.
WARN_UNUSED_RESULT int modifyIpRule(uint16_t action, uint32_t priority, uint8_t ruleType,
uint32_t table, uint32_t fwmark, uint32_t mask, const char* iif,
const char* oif, uid_t uidStart, uid_t uidEnd) {
// Ensure that if you set a bit in the fwmark, it's not being ignored by the mask.
if (fwmark & ~mask) {
ALOGE("mask 0x%x does not select all the bits set in fwmark 0x%x", mask, fwmark);
return -ERANGE;
}
// Interface names must include exactly one terminating NULL and be properly padded, or older
// kernels will refuse to delete rules.
char iifName[IFNAMSIZ], oifName[IFNAMSIZ];
size_t iifLength, oifLength;
uint16_t iifPadding, oifPadding;
if (int ret = padInterfaceName(iif, iifName, &iifLength, &iifPadding)) {
return ret;
}
if (int ret = padInterfaceName(oif, oifName, &oifLength, &oifPadding)) {
return ret;
}
// Either both start and end UID must be specified, or neither.
if ((uidStart == INVALID_UID) != (uidEnd == INVALID_UID)) {
ALOGE("incompatible start and end UIDs (%u vs %u)", uidStart, uidEnd);
return -EUSERS;
}
bool isUidRule = (uidStart != INVALID_UID);
// Assemble a rule request and put it in an array of iovec structures.
fib_rule_hdr rule = {
.action = ruleType,
// Note that here we're implicitly setting rule.table to 0. When we want to specify a
// non-zero table, we do this via the FRATTR_TABLE attribute.
};
// Don't ever create a rule that looks up table 0, because table 0 is the local table.
// It's OK to specify a table ID of 0 when deleting a rule, because that doesn't actually select
// table 0, it's a wildcard that matches anything.
if (table == RT_TABLE_UNSPEC && rule.action == FR_ACT_TO_TBL && action != RTM_DELRULE) {
ALOGE("RT_TABLE_UNSPEC only allowed when deleting rules");
return -ENOTUNIQ;
}
rtattr fraIifName = { U16_RTA_LENGTH(iifLength), FRA_IIFNAME };
rtattr fraOifName = { U16_RTA_LENGTH(oifLength), FRA_OIFNAME };
struct fib_rule_uid_range uidRange = { uidStart, uidEnd };
iovec iov[] = {
{ nullptr, 0 },
{ &rule, sizeof(rule) },
{ &FRATTR_PRIORITY, sizeof(FRATTR_PRIORITY) },
{ &priority, sizeof(priority) },
{ &FRATTR_TABLE, table != RT_TABLE_UNSPEC ? sizeof(FRATTR_TABLE) : 0 },
{ &table, table != RT_TABLE_UNSPEC ? sizeof(table) : 0 },
{ &FRATTR_FWMARK, mask ? sizeof(FRATTR_FWMARK) : 0 },
{ &fwmark, mask ? sizeof(fwmark) : 0 },
{ &FRATTR_FWMASK, mask ? sizeof(FRATTR_FWMASK) : 0 },
{ &mask, mask ? sizeof(mask) : 0 },
{ &FRATTR_UID_RANGE, isUidRule ? sizeof(FRATTR_UID_RANGE) : 0 },
{ &uidRange, isUidRule ? sizeof(uidRange) : 0 },
{ &fraIifName, iif != IIF_NONE ? sizeof(fraIifName) : 0 },
{ iifName, iifLength },
{ PADDING_BUFFER, iifPadding },
{ &fraOifName, oif != OIF_NONE ? sizeof(fraOifName) : 0 },
{ oifName, oifLength },
{ PADDING_BUFFER, oifPadding },
};
uint16_t flags = (action == RTM_NEWRULE) ? NETLINK_RULE_CREATE_FLAGS : NETLINK_REQUEST_FLAGS;
for (size_t i = 0; i < ARRAY_SIZE(AF_FAMILIES); ++i) {
rule.family = AF_FAMILIES[i];
if (int ret = sendNetlinkRequest(action, flags, iov, ARRAY_SIZE(iov), nullptr)) {
if (!(action == RTM_DELRULE && ret == -ENOENT && priority == RULE_PRIORITY_TETHERING)) {
// Don't log when deleting a tethering rule that's not there. This matches the
// behaviour of clearTetheringRules, which ignores ENOENT in this case.
ALOGE("Error %s %s rule: %s", actionName(action), familyName(rule.family),
strerror(-ret));
}
return ret;
}
}
return 0;
}