mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
Merge "Implement waiting for IPv4 address for an interface"
This commit is contained in:
committed by
Android (Google) Code Review
commit
8bfa197e89
@@ -47,7 +47,7 @@ static SocketParams getSocketParams(int domain) {
|
||||
return params;
|
||||
}
|
||||
|
||||
bool send(unsigned long request, struct ifreq& ifr) {
|
||||
int trySend(unsigned long request, struct ifreq& ifr) {
|
||||
const auto sp = getSocketParams(socketDomain);
|
||||
base::unique_fd sock(socket(sp.domain, sp.type, sp.protocol));
|
||||
if (!sock.ok()) {
|
||||
@@ -55,7 +55,12 @@ bool send(unsigned long request, struct ifreq& ifr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ioctl(sock.get(), request, &ifr) < 0) {
|
||||
if (ioctl(sock.get(), request, &ifr) < 0) return errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool send(unsigned long request, struct ifreq& ifr) {
|
||||
if (trySend(request, ifr) != 0) {
|
||||
PLOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,15 @@ namespace android::netdevice::ifreqs {
|
||||
*/
|
||||
extern std::atomic_int socketDomain;
|
||||
|
||||
/**
|
||||
* Tries to send ioctl interface request.
|
||||
*
|
||||
* \param request Request type (such as SIOCGIFFLAGS)
|
||||
* \param ifr Request data (both input and output)
|
||||
* \return error code of the call (0 for success)
|
||||
*/
|
||||
int trySend(unsigned long request, struct ifreq& ifr);
|
||||
|
||||
/**
|
||||
* Sends ioctl interface request.
|
||||
*
|
||||
|
||||
@@ -67,21 +67,33 @@ enum class WaitCondition {
|
||||
*/
|
||||
PRESENT_AND_UP,
|
||||
|
||||
/**
|
||||
* Interface is up and with IPv4 address configured.
|
||||
*/
|
||||
PRESENT_AND_IPV4,
|
||||
|
||||
/**
|
||||
* Interface is down or not present (disconnected) at all.
|
||||
*/
|
||||
DOWN_OR_GONE,
|
||||
};
|
||||
|
||||
enum class Quantifier {
|
||||
ALL_OF,
|
||||
ANY_OF,
|
||||
};
|
||||
|
||||
/**
|
||||
* Listens for interface changes until anticipated condition takes place.
|
||||
*
|
||||
* \param ifnames List of interfaces to watch for.
|
||||
* \param cnd Awaited condition.
|
||||
* \param allOf true if all interfaces need to satisfy the condition, false if only one satistying
|
||||
* \param quant Whether all interfaces need to satisfy the condition or just one satistying
|
||||
* interface should stop the wait.
|
||||
* \return name of one interface that satisfied the condition
|
||||
*/
|
||||
void waitFor(std::set<std::string> ifnames, WaitCondition cnd, bool allOf = true);
|
||||
std::optional<std::string> waitFor(std::set<std::string> ifnames, WaitCondition cnd,
|
||||
Quantifier quant = Quantifier::ALL_OF);
|
||||
|
||||
/**
|
||||
* Brings network interface up.
|
||||
|
||||
@@ -100,23 +100,36 @@ std::optional<bool> isUp(std::string ifname) {
|
||||
return ifr.ifr_flags & IFF_UP;
|
||||
}
|
||||
|
||||
static bool hasIpv4(std::string ifname) {
|
||||
auto ifr = ifreqs::fromName(ifname);
|
||||
switch (const auto status = ifreqs::trySend(SIOCGIFADDR, ifr)) {
|
||||
case 0:
|
||||
return true;
|
||||
case EADDRNOTAVAIL:
|
||||
case ENODEV:
|
||||
return false;
|
||||
default:
|
||||
PLOG(WARNING) << "Failed checking IPv4 address";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct WaitState {
|
||||
bool present;
|
||||
bool up;
|
||||
bool hasIpv4Addr;
|
||||
|
||||
bool satisfied(WaitCondition cnd) const {
|
||||
switch (cnd) {
|
||||
case WaitCondition::PRESENT:
|
||||
if (present) return true;
|
||||
break;
|
||||
return present;
|
||||
case WaitCondition::PRESENT_AND_UP:
|
||||
if (present && up) return true;
|
||||
break;
|
||||
return present && up;
|
||||
case WaitCondition::PRESENT_AND_IPV4:
|
||||
return present && up && hasIpv4Addr;
|
||||
case WaitCondition::DOWN_OR_GONE:
|
||||
if (!present || !up) return true;
|
||||
break;
|
||||
return !present || !up;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,11 +139,22 @@ static std::string toString(WaitCondition cnd) {
|
||||
return "become present";
|
||||
case WaitCondition::PRESENT_AND_UP:
|
||||
return "come up";
|
||||
case WaitCondition::PRESENT_AND_IPV4:
|
||||
return "get IPv4 address";
|
||||
case WaitCondition::DOWN_OR_GONE:
|
||||
return "go down";
|
||||
}
|
||||
}
|
||||
|
||||
static std::string toString(Quantifier quant) {
|
||||
switch (quant) {
|
||||
case Quantifier::ALL_OF:
|
||||
return "all of";
|
||||
case Quantifier::ANY_OF:
|
||||
return "any of";
|
||||
}
|
||||
}
|
||||
|
||||
static std::string toString(const std::set<std::string>& ifnames) {
|
||||
std::stringstream ss;
|
||||
std::copy(ifnames.begin(), ifnames.end(), std::ostream_iterator<std::string>(ss, ","));
|
||||
@@ -139,50 +163,73 @@ static std::string toString(const std::set<std::string>& ifnames) {
|
||||
return str;
|
||||
}
|
||||
|
||||
void waitFor(std::set<std::string> ifnames, WaitCondition cnd, bool allOf) {
|
||||
nl::Socket sock(NETLINK_ROUTE, 0, RTMGRP_LINK);
|
||||
std::optional<std::string> waitFor(std::set<std::string> ifnames, WaitCondition cnd,
|
||||
Quantifier quant) {
|
||||
nl::Socket sock(NETLINK_ROUTE, 0, RTMGRP_LINK | RTMGRP_IPV4_IFADDR);
|
||||
|
||||
using StatesMap = std::map<std::string, WaitState>;
|
||||
StatesMap states = {};
|
||||
for (const auto ifname : ifnames) {
|
||||
const auto present = exists(ifname);
|
||||
const auto up = present && isUp(ifname).value_or(false);
|
||||
states[ifname] = {present, up};
|
||||
const auto hasIpv4Addr = present && hasIpv4(ifname);
|
||||
states[ifname] = {present, up, hasIpv4Addr};
|
||||
}
|
||||
|
||||
const auto mapConditionChecker = [cnd](const StatesMap::iterator::value_type& it) {
|
||||
return it.second.satisfied(cnd);
|
||||
};
|
||||
const auto isFullySatisfied = [&states, allOf, mapConditionChecker]() {
|
||||
if (allOf) {
|
||||
return std::all_of(states.begin(), states.end(), mapConditionChecker);
|
||||
} else {
|
||||
return std::any_of(states.begin(), states.end(), mapConditionChecker);
|
||||
const auto isFullySatisfied = [&states, quant,
|
||||
mapConditionChecker]() -> std::optional<std::string> {
|
||||
if (quant == Quantifier::ALL_OF) {
|
||||
if (!std::all_of(states.begin(), states.end(), mapConditionChecker)) return {};
|
||||
return states.begin()->first;
|
||||
} else { // Quantifier::ANY_OF
|
||||
const auto it = std::find_if(states.begin(), states.end(), mapConditionChecker);
|
||||
if (it == states.end()) return {};
|
||||
return it->first;
|
||||
}
|
||||
};
|
||||
|
||||
if (isFullySatisfied()) return;
|
||||
if (const auto iface = isFullySatisfied()) return iface;
|
||||
|
||||
LOG(DEBUG) << "Waiting for " << (allOf ? "" : "any of ") << toString(ifnames) << " to "
|
||||
LOG(DEBUG) << "Waiting for " << toString(quant) << " " << toString(ifnames) << " to "
|
||||
<< toString(cnd);
|
||||
for (const auto rawMsg : sock) {
|
||||
const auto msg = nl::Message<ifinfomsg>::parse(rawMsg, {RTM_NEWLINK, RTM_DELLINK});
|
||||
if (!msg.has_value()) continue;
|
||||
if (const auto msg = nl::Message<ifinfomsg>::parse(rawMsg, {RTM_NEWLINK, RTM_DELLINK});
|
||||
msg.has_value()) {
|
||||
// Interface added / removed
|
||||
const auto ifname = msg->attributes.get<std::string>(IFLA_IFNAME);
|
||||
if (ifnames.count(ifname) == 0) continue;
|
||||
|
||||
const auto ifname = msg->attributes.get<std::string>(IFLA_IFNAME);
|
||||
if (ifnames.count(ifname) == 0) continue;
|
||||
auto& state = states[ifname];
|
||||
state.present = (msg->header.nlmsg_type != RTM_DELLINK);
|
||||
state.up = state.present && (msg->data.ifi_flags & IFF_UP) != 0;
|
||||
if (!state.present) state.hasIpv4Addr = false;
|
||||
|
||||
const bool present = (msg->header.nlmsg_type != RTM_DELLINK);
|
||||
const bool up = present && (msg->data.ifi_flags & IFF_UP) != 0;
|
||||
states[ifname] = {present, up};
|
||||
} else if (const auto msg =
|
||||
nl::Message<ifaddrmsg>::parse(rawMsg, {RTM_NEWADDR, RTM_DELADDR});
|
||||
msg.has_value()) {
|
||||
// Address added / removed
|
||||
const auto ifname = msg->attributes.get<std::string>(IFLA_IFNAME);
|
||||
if (ifnames.count(ifname) == 0) continue;
|
||||
|
||||
if (isFullySatisfied()) {
|
||||
LOG(DEBUG) << "Finished waiting for " << (allOf ? "" : "some of ") << toString(ifnames)
|
||||
if (msg->header.nlmsg_type == RTM_NEWADDR) {
|
||||
states[ifname].hasIpv4Addr = true;
|
||||
} else {
|
||||
// instead of tracking which one got deleted, let's just ask
|
||||
states[ifname].hasIpv4Addr = hasIpv4(ifname);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto iface = isFullySatisfied()) {
|
||||
LOG(DEBUG) << "Finished waiting for " << toString(quant) << " " << toString(ifnames)
|
||||
<< " to " << toString(cnd);
|
||||
return;
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
LOG(FATAL) << "Can't read Netlink socket";
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace android::netdevice
|
||||
|
||||
@@ -37,8 +37,10 @@ cc_library_static {
|
||||
"protocols/generic/Unknown.cpp",
|
||||
"protocols/generic/families/Mac80211hwsim.cpp",
|
||||
"protocols/generic/families/Nl80211.cpp",
|
||||
"protocols/route/Addr.cpp",
|
||||
"protocols/route/Link.cpp",
|
||||
"protocols/route/Route.cpp",
|
||||
"protocols/route/attributes.cpp",
|
||||
"protocols/route/structs.cpp",
|
||||
"protocols/MessageDefinition.cpp",
|
||||
"protocols/NetlinkProtocol.cpp",
|
||||
|
||||
@@ -34,7 +34,7 @@ const AttributeDefinition AttributeMap::operator[](nlattrtype_t nla_type) const
|
||||
|
||||
MessageDescriptor::MessageDescriptor(const std::string& name,
|
||||
const MessageDetailsMap&& messageDetails,
|
||||
const AttributeMap&& attrTypes, size_t contentsSize)
|
||||
const AttributeMap& attrTypes, size_t contentsSize)
|
||||
: mName(name),
|
||||
mContentsSize(contentsSize),
|
||||
mMessageDetails(messageDetails),
|
||||
|
||||
@@ -163,7 +163,7 @@ class MessageDescriptor {
|
||||
|
||||
protected:
|
||||
MessageDescriptor(const std::string& name, const MessageDetailsMap&& messageDetails,
|
||||
const AttributeMap&& attrTypes, size_t contentsSize);
|
||||
const AttributeMap& attrTypes, size_t contentsSize);
|
||||
|
||||
private:
|
||||
const std::string mName;
|
||||
@@ -183,7 +183,7 @@ class MessageDefinition : public MessageDescriptor {
|
||||
MessageDefinition( //
|
||||
const std::string& name,
|
||||
const std::initializer_list<MessageDescriptor::MessageDetailsMap::value_type> msgDet,
|
||||
const std::initializer_list<AttributeMap::value_type> attrTypes = {})
|
||||
const AttributeMap& attrTypes = {})
|
||||
: MessageDescriptor(name, msgDet, attrTypes, sizeof(T)) {}
|
||||
|
||||
void dataToStream(std::stringstream& ss, const Buffer<nlmsghdr> hdr) const override {
|
||||
|
||||
@@ -33,12 +33,12 @@ static std::map<int, std::shared_ptr<NetlinkProtocol>> toMap(
|
||||
return map;
|
||||
}
|
||||
|
||||
static auto all = toMap({
|
||||
std::make_unique<generic::Generic>(),
|
||||
std::make_unique<route::Route>(),
|
||||
});
|
||||
|
||||
std::optional<std::reference_wrapper<NetlinkProtocol>> get(int protocol) {
|
||||
static auto all = toMap({
|
||||
std::make_unique<generic::Generic>(),
|
||||
std::make_unique<route::Route>(),
|
||||
});
|
||||
|
||||
if (all.count(protocol) == 0) return std::nullopt;
|
||||
return *all.find(protocol)->second.get();
|
||||
}
|
||||
|
||||
58
automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp
Normal file
58
automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#include "Addr.h"
|
||||
|
||||
#include "../structs.h"
|
||||
#include "attributes.h"
|
||||
#include "structs.h"
|
||||
|
||||
namespace android::nl::protocols::route {
|
||||
|
||||
using DataType = AttributeDefinition::DataType;
|
||||
|
||||
// clang-format off
|
||||
Addr::Addr() : MessageDefinition<ifaddrmsg>("addr", {
|
||||
{RTM_NEWADDR, {"NEWADDR", MessageGenre::New}},
|
||||
{RTM_DELADDR, {"DELADDR", MessageGenre::Delete}},
|
||||
{RTM_GETADDR, {"GETADDR", MessageGenre::Get}},
|
||||
}, gAttributes) {}
|
||||
|
||||
static const FlagsMap ifaFlagsMap {
|
||||
{IFA_F_SECONDARY, "SECONDARY"},
|
||||
{IFA_F_NODAD, "NODAD"},
|
||||
{IFA_F_OPTIMISTIC, "OPTIMISTIC"},
|
||||
{IFA_F_DADFAILED, "DADFAILED"},
|
||||
{IFA_F_HOMEADDRESS, "HOMEADDRESS"},
|
||||
{IFA_F_DEPRECATED, "DEPRECATED"},
|
||||
{IFA_F_TENTATIVE, "TENTATIVE"},
|
||||
{IFA_F_PERMANENT, "PERMANENT"},
|
||||
{IFA_F_MANAGETEMPADDR, "MANAGETEMPADDR"},
|
||||
{IFA_F_NOPREFIXROUTE, "NOPREFIXROUTE"},
|
||||
{IFA_F_MCAUTOJOIN, "MCAUTOJOIN"},
|
||||
{IFA_F_STABLE_PRIVACY, "STABLE_PRIVACY"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
void Addr::toStream(std::stringstream& ss, const ifaddrmsg& data) const {
|
||||
ss << "ifaddrmsg{"
|
||||
<< "family=" << familyToString(data.ifa_family)
|
||||
<< ", prefixlen=" << unsigned(data.ifa_prefixlen) << ", flags=";
|
||||
flagsToStream(ss, ifaFlagsMap, data.ifa_flags);
|
||||
ss << ", scope=" << unsigned(data.ifa_scope) << ", index=" << data.ifa_index << "}";
|
||||
}
|
||||
|
||||
} // namespace android::nl::protocols::route
|
||||
31
automotive/can/1.0/default/libnl++/protocols/route/Addr.h
Normal file
31
automotive/can/1.0/default/libnl++/protocols/route/Addr.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../MessageDefinition.h"
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
namespace android::nl::protocols::route {
|
||||
|
||||
class Addr : public MessageDefinition<ifaddrmsg> {
|
||||
public:
|
||||
Addr();
|
||||
void toStream(std::stringstream& ss, const ifaddrmsg& data) const override;
|
||||
};
|
||||
|
||||
} // namespace android::nl::protocols::route
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
#include "Link.h"
|
||||
|
||||
#include "../structs.h"
|
||||
#include "structs.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include "attributes.h"
|
||||
|
||||
namespace android::nl::protocols::route {
|
||||
|
||||
@@ -30,83 +27,8 @@ Link::Link() : MessageDefinition<ifinfomsg>("link", {
|
||||
{RTM_NEWLINK, {"NEWLINK", MessageGenre::New}},
|
||||
{RTM_DELLINK, {"DELLINK", MessageGenre::Delete}},
|
||||
{RTM_GETLINK, {"GETLINK", MessageGenre::Get}},
|
||||
}, {
|
||||
{IFLA_ADDRESS, {"ADDRESS"}},
|
||||
{IFLA_BROADCAST, {"BROADCAST"}},
|
||||
{IFLA_IFNAME, {"IFNAME", DataType::String}},
|
||||
{IFLA_MTU, {"MTU", DataType::Uint}},
|
||||
{IFLA_LINK, {"LINK", DataType::Uint}},
|
||||
{IFLA_QDISC, {"QDISC", DataType::String}},
|
||||
{IFLA_STATS, {"STATS", DataType::Struct, statsToStream<rtnl_link_stats>}},
|
||||
{IFLA_COST, {"COST"}},
|
||||
{IFLA_PRIORITY, {"PRIORITY"}},
|
||||
{IFLA_MASTER, {"MASTER", DataType::Uint}},
|
||||
{IFLA_WIRELESS, {"WIRELESS"}},
|
||||
{IFLA_PROTINFO, {"PROTINFO"}},
|
||||
{IFLA_TXQLEN, {"TXQLEN", DataType::Uint}},
|
||||
{IFLA_MAP, {"MAP", DataType::Struct, mapToStream}},
|
||||
{IFLA_WEIGHT, {"WEIGHT", DataType::Uint}},
|
||||
{IFLA_OPERSTATE, {"OPERSTATE", DataType::Uint}},
|
||||
{IFLA_LINKMODE, {"LINKMODE", DataType::Uint}},
|
||||
{IFLA_LINKINFO, {"LINKINFO", DataType::Nested, AttributeMap{
|
||||
{IFLA_INFO_KIND, {"INFO_KIND", DataType::String}},
|
||||
{IFLA_INFO_DATA, {"INFO_DATA", DataType::Nested}},
|
||||
{IFLA_INFO_XSTATS, {"INFO_XSTATS"}},
|
||||
{IFLA_INFO_SLAVE_KIND, {"INFO_SLAVE_KIND", DataType::String}},
|
||||
{IFLA_INFO_SLAVE_DATA, {"INFO_SLAVE_DATA"}},
|
||||
}}},
|
||||
{IFLA_NET_NS_PID, {"NET_NS_PID", DataType::Uint}},
|
||||
{IFLA_IFALIAS, {"IFALIAS", DataType::String}},
|
||||
{IFLA_NUM_VF, {"NUM_VF", DataType::Uint}},
|
||||
{IFLA_VFINFO_LIST, {"VFINFO_LIST"}},
|
||||
{IFLA_STATS64, {"STATS64", DataType::Struct, statsToStream<rtnl_link_stats64>}},
|
||||
{IFLA_VF_PORTS, {"VF_PORTS"}},
|
||||
{IFLA_PORT_SELF, {"PORT_SELF"}},
|
||||
{IFLA_AF_SPEC, {"AF_SPEC", DataType::Nested, AttributeMap{
|
||||
{AF_INET, {"AF_INET", DataType::Nested, AttributeMap{
|
||||
{IFLA_INET_CONF, {"INET_CONF", DataType::Struct, arrayToStream<int32_t>}},
|
||||
}}},
|
||||
{AF_INET6, {"AF_INET6", DataType::Nested, AttributeMap{
|
||||
{IFLA_INET6_FLAGS, {"INET6_FLAGS", DataType::Uint}},
|
||||
{IFLA_INET6_CONF, {"INET6_CONF", DataType::Struct, arrayToStream<int32_t>}},
|
||||
{IFLA_INET6_STATS, {"INET6_STATS", DataType::Struct, arrayToStream<uint64_t>}},
|
||||
{IFLA_INET6_MCAST, {"INET6_MCAST"}},
|
||||
{IFLA_INET6_CACHEINFO, {"INET6_CACHEINFO", DataType::Struct, ifla_cacheinfoToStream}},
|
||||
{IFLA_INET6_ICMP6STATS, {"INET6_ICMP6STATS", DataType::Struct, arrayToStream<uint64_t>}},
|
||||
{IFLA_INET6_TOKEN, {"INET6_TOKEN"}},
|
||||
{IFLA_INET6_ADDR_GEN_MODE, {"INET6_ADDR_GEN_MODE", DataType::Uint}},
|
||||
}}},
|
||||
}}},
|
||||
{IFLA_GROUP, {"GROUP", DataType::Uint}},
|
||||
{IFLA_NET_NS_FD, {"NET_NS_FD", DataType::Uint}},
|
||||
{IFLA_EXT_MASK, {"EXT_MASK", DataType::Uint}},
|
||||
{IFLA_PROMISCUITY, {"PROMISCUITY", DataType::Uint}},
|
||||
{IFLA_NUM_TX_QUEUES, {"NUM_TX_QUEUES", DataType::Uint}},
|
||||
{IFLA_NUM_RX_QUEUES, {"NUM_RX_QUEUES", DataType::Uint}},
|
||||
{IFLA_CARRIER, {"CARRIER", DataType::Uint}},
|
||||
{IFLA_PHYS_PORT_ID, {"PHYS_PORT_ID"}},
|
||||
{IFLA_CARRIER_CHANGES, {"CARRIER_CHANGES", DataType::Uint}},
|
||||
{IFLA_PHYS_SWITCH_ID, {"PHYS_SWITCH_ID"}},
|
||||
{IFLA_LINK_NETNSID, {"LINK_NETNSID"}}, // NLA_S32
|
||||
{IFLA_PHYS_PORT_NAME, {"PHYS_PORT_NAME", DataType::String}},
|
||||
{IFLA_PROTO_DOWN, {"PROTO_DOWN", DataType::Uint}},
|
||||
{IFLA_GSO_MAX_SEGS, {"GSO_MAX_SEGS", DataType::Uint}},
|
||||
{IFLA_GSO_MAX_SIZE, {"GSO_MAX_SIZE", DataType::Uint}},
|
||||
{IFLA_PAD, {"PAD"}},
|
||||
{IFLA_XDP, {"XDP"}},
|
||||
{IFLA_EVENT, {"EVENT", DataType::Uint}},
|
||||
{IFLA_NEW_NETNSID, {"NEW_NETNSID"}}, // NLA_S32
|
||||
{IFLA_TARGET_NETNSID, {"TARGET_NETNSID"}}, // NLA_S32
|
||||
{IFLA_CARRIER_UP_COUNT, {"CARRIER_UP_COUNT", DataType::Uint}},
|
||||
{IFLA_CARRIER_DOWN_COUNT, {"CARRIER_DOWN_COUNT", DataType::Uint}},
|
||||
{IFLA_NEW_IFINDEX, {"NEW_IFINDEX"}}, // NLA_S32
|
||||
{IFLA_MIN_MTU, {"MIN_MTU", DataType::Uint}},
|
||||
{IFLA_MAX_MTU, {"MAX_MTU", DataType::Uint}},
|
||||
{IFLA_PROP_LIST, {"PROP_LIST"}},
|
||||
{IFLA_ALT_IFNAME, {"ALT_IFNAME", DataType::String}},
|
||||
{IFLA_PERM_ADDRESS, {"PERM_ADDRESS"}},
|
||||
}) {}
|
||||
// clang-format off
|
||||
}, gAttributes) {}
|
||||
// clang-format on
|
||||
|
||||
void Link::toStream(std::stringstream& ss, const ifinfomsg& data) const {
|
||||
ss << "ifinfomsg{"
|
||||
|
||||
@@ -16,10 +16,16 @@
|
||||
|
||||
#include "Route.h"
|
||||
|
||||
#include "Addr.h"
|
||||
#include "Link.h"
|
||||
|
||||
namespace android::nl::protocols::route {
|
||||
|
||||
Route::Route() : NetlinkProtocol(NETLINK_ROUTE, "ROUTE", {std::make_shared<Link>()}) {}
|
||||
// clang-format off
|
||||
Route::Route() : NetlinkProtocol(NETLINK_ROUTE, "ROUTE", {
|
||||
std::make_shared<Addr>(),
|
||||
std::make_shared<Link>(),
|
||||
}) {}
|
||||
// clang-format on
|
||||
|
||||
} // namespace android::nl::protocols::route
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#include "attributes.h"
|
||||
|
||||
#include "../structs.h"
|
||||
#include "structs.h"
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/if.h>
|
||||
|
||||
namespace android::nl::protocols::route {
|
||||
|
||||
using DataType = AttributeDefinition::DataType;
|
||||
using Flags = AttributeDefinition::Flags;
|
||||
|
||||
// clang-format off
|
||||
AttributeMap gAttributes = {
|
||||
{IFLA_ADDRESS, {"ADDRESS"}},
|
||||
{IFLA_BROADCAST, {"BROADCAST"}},
|
||||
{IFLA_IFNAME, {"IFNAME", DataType::StringNul}},
|
||||
{IFLA_MTU, {"MTU", DataType::Uint}},
|
||||
{IFLA_LINK, {"LINK", DataType::Uint}},
|
||||
{IFLA_QDISC, {"QDISC", DataType::Raw, AttributeMap{}, Flags::Verbose}}, // should be DataType::String, but looks like binary blob
|
||||
{IFLA_STATS, {"STATS", DataType::Struct, statsToStream<rtnl_link_stats>}},
|
||||
{IFLA_COST, {"COST", DataType::Uint}},
|
||||
{IFLA_PRIORITY, {"PRIORITY"}},
|
||||
{IFLA_MASTER, {"MASTER", DataType::Uint}},
|
||||
{IFLA_WIRELESS, {"WIRELESS"}},
|
||||
{IFLA_PROTINFO, {"PROTINFO"}},
|
||||
{IFLA_TXQLEN, {"TXQLEN", DataType::Uint}},
|
||||
{IFLA_MAP, {"MAP", DataType::Struct, mapToStream}},
|
||||
{IFLA_WEIGHT, {"WEIGHT", DataType::Uint}},
|
||||
{IFLA_OPERSTATE, {"OPERSTATE", DataType::Uint}},
|
||||
{IFLA_LINKMODE, {"LINKMODE", DataType::Uint}},
|
||||
{IFLA_LINKINFO, {"LINKINFO", DataType::Nested, AttributeMap{
|
||||
{IFLA_INFO_KIND, {"INFO_KIND", DataType::String}},
|
||||
{IFLA_INFO_DATA, {"INFO_DATA", DataType::Nested}},
|
||||
{IFLA_INFO_XSTATS, {"INFO_XSTATS"}},
|
||||
{IFLA_INFO_SLAVE_KIND, {"INFO_SLAVE_KIND", DataType::String}},
|
||||
{IFLA_INFO_SLAVE_DATA, {"INFO_SLAVE_DATA"}},
|
||||
}}},
|
||||
{IFLA_NET_NS_PID, {"NET_NS_PID", DataType::Uint}},
|
||||
{IFLA_IFALIAS, {"IFALIAS", DataType::String}},
|
||||
{IFLA_NUM_VF, {"NUM_VF", DataType::Uint}},
|
||||
{IFLA_VFINFO_LIST, {"VFINFO_LIST"}},
|
||||
{IFLA_STATS64, {"STATS64", DataType::Struct, statsToStream<rtnl_link_stats64>}},
|
||||
{IFLA_VF_PORTS, {"VF_PORTS"}},
|
||||
{IFLA_PORT_SELF, {"PORT_SELF"}},
|
||||
{IFLA_AF_SPEC, {"AF_SPEC", DataType::Nested, AttributeMap{
|
||||
{AF_INET, {"AF_INET", DataType::Nested, AttributeMap{
|
||||
{IFLA_INET_CONF, {"INET_CONF", DataType::Struct, arrayToStream<int32_t>}},
|
||||
}}},
|
||||
{AF_INET6, {"AF_INET6", DataType::Nested, AttributeMap{
|
||||
{IFLA_INET6_FLAGS, {"INET6_FLAGS", DataType::Uint}},
|
||||
{IFLA_INET6_CONF, {"INET6_CONF", DataType::Struct, arrayToStream<int32_t>}},
|
||||
{IFLA_INET6_STATS, {"INET6_STATS", DataType::Struct, arrayToStream<uint64_t>}},
|
||||
{IFLA_INET6_MCAST, {"INET6_MCAST"}},
|
||||
{IFLA_INET6_CACHEINFO, {"INET6_CACHEINFO", DataType::Struct, ifla_cacheinfoToStream}},
|
||||
{IFLA_INET6_ICMP6STATS, {"INET6_ICMP6STATS", DataType::Struct, arrayToStream<uint64_t>}},
|
||||
{IFLA_INET6_TOKEN, {"INET6_TOKEN"}},
|
||||
{IFLA_INET6_ADDR_GEN_MODE, {"INET6_ADDR_GEN_MODE", DataType::Uint}},
|
||||
}}},
|
||||
}}},
|
||||
{IFLA_GROUP, {"GROUP", DataType::Uint}},
|
||||
{IFLA_NET_NS_FD, {"NET_NS_FD", DataType::Uint}},
|
||||
{IFLA_EXT_MASK, {"EXT_MASK", DataType::Uint}},
|
||||
{IFLA_PROMISCUITY, {"PROMISCUITY", DataType::Uint}},
|
||||
{IFLA_NUM_TX_QUEUES, {"NUM_TX_QUEUES", DataType::Uint}},
|
||||
{IFLA_NUM_RX_QUEUES, {"NUM_RX_QUEUES", DataType::Uint}},
|
||||
{IFLA_CARRIER, {"CARRIER", DataType::Uint}},
|
||||
{IFLA_PHYS_PORT_ID, {"PHYS_PORT_ID"}},
|
||||
{IFLA_CARRIER_CHANGES, {"CARRIER_CHANGES", DataType::Uint}},
|
||||
{IFLA_PHYS_SWITCH_ID, {"PHYS_SWITCH_ID"}},
|
||||
{IFLA_LINK_NETNSID, {"LINK_NETNSID"}}, // NLA_S32
|
||||
{IFLA_PHYS_PORT_NAME, {"PHYS_PORT_NAME", DataType::String}},
|
||||
{IFLA_PROTO_DOWN, {"PROTO_DOWN", DataType::Uint}},
|
||||
{IFLA_GSO_MAX_SEGS, {"GSO_MAX_SEGS", DataType::Uint}},
|
||||
{IFLA_GSO_MAX_SIZE, {"GSO_MAX_SIZE", DataType::Uint}},
|
||||
{IFLA_PAD, {"PAD"}},
|
||||
{IFLA_XDP, {"XDP"}},
|
||||
{IFLA_EVENT, {"EVENT", DataType::Uint}},
|
||||
{IFLA_NEW_NETNSID, {"NEW_NETNSID"}}, // NLA_S32
|
||||
{IFLA_TARGET_NETNSID, {"TARGET_NETNSID"}}, // NLA_S32
|
||||
{IFLA_CARRIER_UP_COUNT, {"CARRIER_UP_COUNT", DataType::Uint}},
|
||||
{IFLA_CARRIER_DOWN_COUNT, {"CARRIER_DOWN_COUNT", DataType::Uint}},
|
||||
{IFLA_NEW_IFINDEX, {"NEW_IFINDEX"}}, // NLA_S32
|
||||
{IFLA_MIN_MTU, {"MIN_MTU", DataType::Uint}},
|
||||
{IFLA_MAX_MTU, {"MAX_MTU", DataType::Uint}},
|
||||
{IFLA_PROP_LIST, {"PROP_LIST"}},
|
||||
{IFLA_ALT_IFNAME, {"ALT_IFNAME", DataType::String}},
|
||||
{IFLA_PERM_ADDRESS, {"PERM_ADDRESS"}},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
} // namespace android::nl::protocols::route
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../MessageDefinition.h"
|
||||
|
||||
namespace android::nl::protocols::route {
|
||||
|
||||
extern AttributeMap gAttributes;
|
||||
|
||||
} // namespace android::nl::protocols::route
|
||||
@@ -46,4 +46,58 @@ void ifla_cacheinfoToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
|
||||
<< data.retrans_time << '}';
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
std::string familyToString(sa_family_t family) {
|
||||
switch (family) {
|
||||
case AF_UNSPEC: return "UNSPEC";
|
||||
case AF_UNIX: return "UNIX";
|
||||
case AF_INET: return "INET";
|
||||
case AF_AX25: return "AX25";
|
||||
case AF_IPX: return "IPX";
|
||||
case AF_APPLETALK: return "APPLETALK";
|
||||
case AF_NETROM: return "NETROM";
|
||||
case AF_BRIDGE: return "BRIDGE";
|
||||
case AF_ATMPVC: return "ATMPVC";
|
||||
case AF_X25: return "X25";
|
||||
case AF_INET6: return "INET6";
|
||||
case AF_ROSE: return "ROSE";
|
||||
case AF_DECnet: return "DECnet";
|
||||
case AF_NETBEUI: return "NETBEUI";
|
||||
case AF_SECURITY: return "SECURITY";
|
||||
case AF_KEY: return "KEY";
|
||||
case AF_NETLINK: return "NETLINK";
|
||||
case AF_PACKET: return "PACKET";
|
||||
case AF_ASH: return "ASH";
|
||||
case AF_ECONET: return "ECONET";
|
||||
case AF_ATMSVC: return "ATMSVC";
|
||||
case AF_RDS: return "RDS";
|
||||
case AF_SNA: return "SNA";
|
||||
case AF_IRDA: return "IRDA";
|
||||
case AF_PPPOX: return "PPPOX";
|
||||
case AF_WANPIPE: return "WANPIPE";
|
||||
case AF_LLC: return "LLC";
|
||||
case 27 /*AF_IB*/: return "IB";
|
||||
case 28 /*AF_MPLS*/: return "MPLS";
|
||||
case AF_CAN: return "CAN";
|
||||
case AF_TIPC: return "TIPC";
|
||||
case AF_BLUETOOTH: return "BLUETOOTH";
|
||||
case AF_IUCV: return "IUCV";
|
||||
case AF_RXRPC: return "RXRPC";
|
||||
case AF_ISDN: return "ISDN";
|
||||
case AF_PHONET: return "PHONET";
|
||||
case AF_IEEE802154: return "IEEE802154";
|
||||
case AF_CAIF: return "CAIF";
|
||||
case AF_ALG: return "ALG";
|
||||
case AF_NFC: return "NFC";
|
||||
case AF_VSOCK: return "VSOCK";
|
||||
case AF_KCM: return "KCM";
|
||||
case AF_QIPCRTR: return "QIPCRTR";
|
||||
case 43 /*AF_SMC*/: return "SMC";
|
||||
case 44 /*AF_XDP*/: return "XDP";
|
||||
default:
|
||||
return std::to_string(family);
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
} // namespace android::nl::protocols::route
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <libnl++/Buffer.h>
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
@@ -30,6 +31,8 @@ void mapToStream(std::stringstream& ss, const Buffer<nlattr> attr);
|
||||
// ifla_cacheinfo
|
||||
void ifla_cacheinfoToStream(std::stringstream& ss, const Buffer<nlattr> attr);
|
||||
|
||||
std::string familyToString(sa_family_t family);
|
||||
|
||||
// rtnl_link_stats or rtnl_link_stats64
|
||||
template <typename T>
|
||||
void statsToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
|
||||
|
||||
@@ -22,24 +22,27 @@ namespace android::nl::protocols {
|
||||
|
||||
AttributeDefinition::ToStream flagsToStream(FlagsMap flags) {
|
||||
return [flags](std::stringstream& ss, const Buffer<nlattr> attr) {
|
||||
auto val = attr.data<uint64_t>().copyFirst();
|
||||
auto value = attr.data<uint64_t>().copyFirst();
|
||||
flagsToStream(ss, flags, value);
|
||||
};
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
for (const auto& [flag, name] : flags) {
|
||||
if ((val & flag) != flag) continue;
|
||||
val &= ~flag;
|
||||
|
||||
if (!first) ss << '|';
|
||||
first = false;
|
||||
|
||||
ss << name;
|
||||
}
|
||||
|
||||
if (val == 0) return;
|
||||
void flagsToStream(std::stringstream& ss, const FlagsMap& flags, uint64_t val) {
|
||||
bool first = true;
|
||||
for (const auto& [flag, name] : flags) {
|
||||
if ((val & flag) != flag) continue;
|
||||
val &= ~flag;
|
||||
|
||||
if (!first) ss << '|';
|
||||
ss << std::hex << val << std::dec;
|
||||
};
|
||||
first = false;
|
||||
|
||||
ss << name;
|
||||
}
|
||||
|
||||
if (val == 0) return;
|
||||
|
||||
if (!first) ss << '|';
|
||||
ss << std::hex << val << std::dec;
|
||||
}
|
||||
|
||||
void hwaddrToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
|
||||
|
||||
@@ -34,6 +34,7 @@ void arrayToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
|
||||
|
||||
typedef std::map<uint64_t, std::string> FlagsMap;
|
||||
AttributeDefinition::ToStream flagsToStream(FlagsMap flags);
|
||||
void flagsToStream(std::stringstream& ss, const FlagsMap& flags, uint64_t value);
|
||||
|
||||
void hwaddrToStream(std::stringstream& ss, const Buffer<nlattr> attr);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user