diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp index 8df6434796..8471173d24 100644 --- a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp +++ b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp @@ -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; } diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.h b/automotive/can/1.0/default/libnetdevice/ifreqs.h index 74e58775b6..d8d6fe0cd4 100644 --- a/automotive/can/1.0/default/libnetdevice/ifreqs.h +++ b/automotive/can/1.0/default/libnetdevice/ifreqs.h @@ -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. * diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h index 70cb688933..657f9b2cc6 100644 --- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h +++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h @@ -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 ifnames, WaitCondition cnd, bool allOf = true); +std::optional waitFor(std::set ifnames, WaitCondition cnd, + Quantifier quant = Quantifier::ALL_OF); /** * Brings network interface up. diff --git a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp index 2d3b41747f..aad07de6d7 100644 --- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp +++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp @@ -100,23 +100,36 @@ std::optional 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& ifnames) { std::stringstream ss; std::copy(ifnames.begin(), ifnames.end(), std::ostream_iterator(ss, ",")); @@ -139,50 +163,73 @@ static std::string toString(const std::set& ifnames) { return str; } -void waitFor(std::set ifnames, WaitCondition cnd, bool allOf) { - nl::Socket sock(NETLINK_ROUTE, 0, RTMGRP_LINK); +std::optional waitFor(std::set ifnames, WaitCondition cnd, + Quantifier quant) { + nl::Socket sock(NETLINK_ROUTE, 0, RTMGRP_LINK | RTMGRP_IPV4_IFADDR); using StatesMap = std::map; 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 { + 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::parse(rawMsg, {RTM_NEWLINK, RTM_DELLINK}); - if (!msg.has_value()) continue; + if (const auto msg = nl::Message::parse(rawMsg, {RTM_NEWLINK, RTM_DELLINK}); + msg.has_value()) { + // Interface added / removed + const auto ifname = msg->attributes.get(IFLA_IFNAME); + if (ifnames.count(ifname) == 0) continue; - const auto ifname = msg->attributes.get(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::parse(rawMsg, {RTM_NEWADDR, RTM_DELADDR}); + msg.has_value()) { + // Address added / removed + const auto ifname = msg->attributes.get(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 diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp index 2ebd1b4732..01c1e55ca9 100644 --- a/automotive/can/1.0/default/libnl++/Android.bp +++ b/automotive/can/1.0/default/libnl++/Android.bp @@ -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", diff --git a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp index aaf24a53aa..158d2a1e95 100644 --- a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.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), diff --git a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h index 8bed5e7a7e..33ded9a44d 100644 --- a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h +++ b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h @@ -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 msgDet, - const std::initializer_list attrTypes = {}) + const AttributeMap& attrTypes = {}) : MessageDescriptor(name, msgDet, attrTypes, sizeof(T)) {} void dataToStream(std::stringstream& ss, const Buffer hdr) const override { diff --git a/automotive/can/1.0/default/libnl++/protocols/all.cpp b/automotive/can/1.0/default/libnl++/protocols/all.cpp index a398dc8f1f..72c60f251f 100644 --- a/automotive/can/1.0/default/libnl++/protocols/all.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/all.cpp @@ -33,12 +33,12 @@ static std::map> toMap( return map; } -static auto all = toMap({ - std::make_unique(), - std::make_unique(), -}); - std::optional> get(int protocol) { + static auto all = toMap({ + std::make_unique(), + std::make_unique(), + }); + if (all.count(protocol) == 0) return std::nullopt; return *all.find(protocol)->second.get(); } diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp b/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp new file mode 100644 index 0000000000..024d3891b6 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/Addr.cpp @@ -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("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 diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Addr.h b/automotive/can/1.0/default/libnl++/protocols/route/Addr.h new file mode 100644 index 0000000000..b6b8bdca3f --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/Addr.h @@ -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 + +namespace android::nl::protocols::route { + +class Addr : public MessageDefinition { + public: + Addr(); + void toStream(std::stringstream& ss, const ifaddrmsg& data) const override; +}; + +} // namespace android::nl::protocols::route diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp b/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp index 9cc05da027..3dd0066732 100644 --- a/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp @@ -16,10 +16,7 @@ #include "Link.h" -#include "../structs.h" -#include "structs.h" - -#include +#include "attributes.h" namespace android::nl::protocols::route { @@ -30,83 +27,8 @@ Link::Link() : MessageDefinition("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}}, - {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}}, - {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}}, - }}}, - {AF_INET6, {"AF_INET6", DataType::Nested, AttributeMap{ - {IFLA_INET6_FLAGS, {"INET6_FLAGS", DataType::Uint}}, - {IFLA_INET6_CONF, {"INET6_CONF", DataType::Struct, arrayToStream}}, - {IFLA_INET6_STATS, {"INET6_STATS", DataType::Struct, arrayToStream}}, - {IFLA_INET6_MCAST, {"INET6_MCAST"}}, - {IFLA_INET6_CACHEINFO, {"INET6_CACHEINFO", DataType::Struct, ifla_cacheinfoToStream}}, - {IFLA_INET6_ICMP6STATS, {"INET6_ICMP6STATS", DataType::Struct, arrayToStream}}, - {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{" diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Route.cpp b/automotive/can/1.0/default/libnl++/protocols/route/Route.cpp index c134911525..51e5b11b74 100644 --- a/automotive/can/1.0/default/libnl++/protocols/route/Route.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/route/Route.cpp @@ -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()}) {} +// clang-format off +Route::Route() : NetlinkProtocol(NETLINK_ROUTE, "ROUTE", { + std::make_shared(), + std::make_shared(), +}) {} +// clang-format on } // namespace android::nl::protocols::route diff --git a/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp b/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp new file mode 100644 index 0000000000..69d9b811a9 --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/attributes.cpp @@ -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 +#include + +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}}, + {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}}, + {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}}, + }}}, + {AF_INET6, {"AF_INET6", DataType::Nested, AttributeMap{ + {IFLA_INET6_FLAGS, {"INET6_FLAGS", DataType::Uint}}, + {IFLA_INET6_CONF, {"INET6_CONF", DataType::Struct, arrayToStream}}, + {IFLA_INET6_STATS, {"INET6_STATS", DataType::Struct, arrayToStream}}, + {IFLA_INET6_MCAST, {"INET6_MCAST"}}, + {IFLA_INET6_CACHEINFO, {"INET6_CACHEINFO", DataType::Struct, ifla_cacheinfoToStream}}, + {IFLA_INET6_ICMP6STATS, {"INET6_ICMP6STATS", DataType::Struct, arrayToStream}}, + {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 diff --git a/automotive/can/1.0/default/libnl++/protocols/route/attributes.h b/automotive/can/1.0/default/libnl++/protocols/route/attributes.h new file mode 100644 index 0000000000..ace9234f3b --- /dev/null +++ b/automotive/can/1.0/default/libnl++/protocols/route/attributes.h @@ -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 diff --git a/automotive/can/1.0/default/libnl++/protocols/route/structs.cpp b/automotive/can/1.0/default/libnl++/protocols/route/structs.cpp index b62cec3c7e..269771c423 100644 --- a/automotive/can/1.0/default/libnl++/protocols/route/structs.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/route/structs.cpp @@ -46,4 +46,58 @@ void ifla_cacheinfoToStream(std::stringstream& ss, const Buffer 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 diff --git a/automotive/can/1.0/default/libnl++/protocols/route/structs.h b/automotive/can/1.0/default/libnl++/protocols/route/structs.h index fea2ce130c..c969a6c8cb 100644 --- a/automotive/can/1.0/default/libnl++/protocols/route/structs.h +++ b/automotive/can/1.0/default/libnl++/protocols/route/structs.h @@ -19,6 +19,7 @@ #include #include +#include #include @@ -30,6 +31,8 @@ void mapToStream(std::stringstream& ss, const Buffer attr); // ifla_cacheinfo void ifla_cacheinfoToStream(std::stringstream& ss, const Buffer attr); +std::string familyToString(sa_family_t family); + // rtnl_link_stats or rtnl_link_stats64 template void statsToStream(std::stringstream& ss, const Buffer attr) { diff --git a/automotive/can/1.0/default/libnl++/protocols/structs.cpp b/automotive/can/1.0/default/libnl++/protocols/structs.cpp index 8ff71f006a..3f896bffe2 100644 --- a/automotive/can/1.0/default/libnl++/protocols/structs.cpp +++ b/automotive/can/1.0/default/libnl++/protocols/structs.cpp @@ -22,24 +22,27 @@ namespace android::nl::protocols { AttributeDefinition::ToStream flagsToStream(FlagsMap flags) { return [flags](std::stringstream& ss, const Buffer attr) { - auto val = attr.data().copyFirst(); + auto value = attr.data().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 attr) { diff --git a/automotive/can/1.0/default/libnl++/protocols/structs.h b/automotive/can/1.0/default/libnl++/protocols/structs.h index f3a8c44afe..9cf6f1ae57 100644 --- a/automotive/can/1.0/default/libnl++/protocols/structs.h +++ b/automotive/can/1.0/default/libnl++/protocols/structs.h @@ -34,6 +34,7 @@ void arrayToStream(std::stringstream& ss, const Buffer attr) { typedef std::map FlagsMap; AttributeDefinition::ToStream flagsToStream(FlagsMap flags); +void flagsToStream(std::stringstream& ss, const FlagsMap& flags, uint64_t value); void hwaddrToStream(std::stringstream& ss, const Buffer attr);