diff --git a/automotive/can/1.0/default/libnetdevice/Android.bp b/automotive/can/1.0/default/libnetdevice/Android.bp index 928ad1339a..d49b9abb17 100644 --- a/automotive/can/1.0/default/libnetdevice/Android.bp +++ b/automotive/can/1.0/default/libnetdevice/Android.bp @@ -28,6 +28,7 @@ cc_library_static { "protocols/generic/Unknown.cpp", "protocols/route/Link.cpp", "protocols/route/Route.cpp", + "protocols/route/structs.cpp", "protocols/MessageDefinition.cpp", "protocols/NetlinkProtocol.cpp", "protocols/all.cpp", diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h index 17815f9b7b..601ab942af 100644 --- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h +++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h @@ -66,9 +66,12 @@ class nlbuf { return mData; } - std::optional> getFirst() const { - if (!ok()) return std::nullopt; - return *mData; + std::pair getFirst() const { + if (!ok()) { + static const T dummy = {}; + return {false, dummy}; + } + return {true, *mData}; } /** @@ -141,7 +144,7 @@ class nlbuf { size_t len() const { return mBuffer.remainingLength(); } private: - const nlbuf& mBuffer; + const nlbuf mBuffer; }; raw_view getRaw() const { return {*this}; } @@ -160,8 +163,12 @@ class nlbuf { size_t declaredLength() const { // We can't even fit a header, so let's return some absurd high value to trip off // buffer overflow checks. - if (sizeof(T) > remainingLength()) return std::numeric_limits::max() / 2; - return declaredLengthImpl(); + static constexpr size_t badHeaderLength = std::numeric_limits::max() / 2; + + if (sizeof(T) > remainingLength()) return badHeaderLength; + const auto len = declaredLengthImpl(); + if (sizeof(T) > len) return badHeaderLength; + return len; } size_t remainingLength() const { diff --git a/automotive/can/1.0/default/libnetdevice/printer.cpp b/automotive/can/1.0/default/libnetdevice/printer.cpp index 0076dd68cf..f6c9c6072b 100644 --- a/automotive/can/1.0/default/libnetdevice/printer.cpp +++ b/automotive/can/1.0/default/libnetdevice/printer.cpp @@ -85,17 +85,16 @@ static void toStream(std::stringstream& ss, const nlbuf attr, ss << attrtype.name << ": "; switch (attrtype.dataType) { - case DataType::Raw: { + case DataType::Raw: toStream(ss, attr.data()); break; - } case DataType::Nested: { ss << '{'; bool first = true; - for (auto childattr : attr.data()) { + for (const auto childattr : attr.data()) { if (!first) ss << ", "; first = false; - toStream(ss, childattr, attrtype.subTypes); + toStream(ss, childattr, std::get(attrtype.ops)); } ss << '}'; break; @@ -105,9 +104,14 @@ static void toStream(std::stringstream& ss, const nlbuf attr, ss << '"' << sanitize({str.ptr(), str.len()}) << '"'; break; } - case DataType::Uint: { + case DataType::Uint: ss << attr.data().copyFirst(); break; + case DataType::Struct: { + const auto structToStream = + std::get(attrtype.ops); + structToStream(ss, attr); + break; } } } diff --git a/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h b/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h index a25e885660..3a8b2b55d0 100644 --- a/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h +++ b/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h @@ -21,6 +21,7 @@ #include #include +#include namespace android::netdevice::protocols { @@ -57,11 +58,13 @@ struct AttributeDefinition { Nested, String, Uint, + Struct, }; + using ToStream = std::function attr)>; std::string name; DataType dataType = DataType::Raw; - AttributeMap subTypes = {}; + std::variant ops = AttributeMap{}; }; /** @@ -107,13 +110,13 @@ class MessageDefinition : public MessageDescriptor { : MessageDescriptor(name, messageTypes, attrTypes, sizeof(T)) {} void dataToStream(std::stringstream& ss, const nlbuf hdr) const override { - const auto msg = hdr.data().getFirst(); - if (!msg.has_value()) { + const auto& [ok, msg] = hdr.data().getFirst(); + if (!ok) { ss << "{incomplete payload}"; return; } - toStream(ss, *msg); + toStream(ss, msg); } protected: diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp index 08b2be7e65..4120008519 100644 --- a/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp +++ b/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp @@ -37,14 +37,14 @@ Ctrl::Ctrl() : GenericMessageBase(GENL_ID_CTRL, "ID_CTRL", { {CTRL_ATTR_VERSION, {"VERSION", DataType::Uint}}, {CTRL_ATTR_HDRSIZE, {"HDRSIZE", DataType::Uint}}, {CTRL_ATTR_MAXATTR, {"MAXATTR", DataType::Uint}}, - {CTRL_ATTR_OPS, {"OPS", DataType::Nested, { - {std::nullopt, {"OP", DataType::Nested, { + {CTRL_ATTR_OPS, {"OPS", DataType::Nested, AttributeMap{ + {std::nullopt, {"OP", DataType::Nested, AttributeMap{ {CTRL_ATTR_OP_ID, {"ID", DataType::Uint}}, {CTRL_ATTR_OP_FLAGS, {"FLAGS", DataType::Uint}}, }}}, }}}, - {CTRL_ATTR_MCAST_GROUPS, {"MCAST_GROUPS", DataType::Nested, { - {std::nullopt, {"GRP", DataType::Nested, { + {CTRL_ATTR_MCAST_GROUPS, {"MCAST_GROUPS", DataType::Nested, AttributeMap{ + {std::nullopt, {"GRP", DataType::Nested, AttributeMap{ {CTRL_ATTR_MCAST_GRP_NAME, {"NAME", DataType::String}}, {CTRL_ATTR_MCAST_GRP_ID, {"ID", DataType::Uint}}, }}}, diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp index 4617d92e09..53e1700219 100644 --- a/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp +++ b/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp @@ -16,6 +16,10 @@ #include "Link.h" +#include "structs.h" + +#include + namespace android::netdevice::protocols::route { using DataType = AttributeDefinition::DataType; @@ -29,62 +33,76 @@ Link::Link() : MessageDefinition("link", { {IFLA_ADDRESS, {"ADDRESS"}}, {IFLA_BROADCAST, {"BROADCAST"}}, {IFLA_IFNAME, {"IFNAME", DataType::String}}, - {IFLA_MTU, {"MTU"}}, + {IFLA_MTU, {"MTU", DataType::Uint}}, {IFLA_LINK, {"LINK", DataType::Uint}}, - {IFLA_QDISC, {"QDISC"}}, - {IFLA_STATS, {"STATS"}}, + {IFLA_QDISC, {"QDISC", DataType::String}}, + {IFLA_STATS, {"STATS", DataType::Struct, statsToStream}}, {IFLA_COST, {"COST"}}, {IFLA_PRIORITY, {"PRIORITY"}}, - {IFLA_MASTER, {"MASTER"}}, + {IFLA_MASTER, {"MASTER", DataType::Uint}}, {IFLA_WIRELESS, {"WIRELESS"}}, {IFLA_PROTINFO, {"PROTINFO"}}, - {IFLA_TXQLEN, {"TXQLEN"}}, - {IFLA_MAP, {"MAP"}}, - {IFLA_WEIGHT, {"WEIGHT"}}, - {IFLA_OPERSTATE, {"OPERSTATE"}}, - {IFLA_LINKMODE, {"LINKMODE"}}, - {IFLA_LINKINFO, {"LINKINFO", DataType::Nested, { + {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"}}, + {IFLA_INFO_SLAVE_KIND, {"INFO_SLAVE_KIND", DataType::String}}, {IFLA_INFO_SLAVE_DATA, {"INFO_SLAVE_DATA"}}, }}}, - {IFLA_NET_NS_PID, {"NET_NS_PID"}}, - {IFLA_IFALIAS, {"IFALIAS"}}, - {IFLA_NUM_VF, {"NUM_VF"}}, + {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"}}, + {IFLA_STATS64, {"STATS64", DataType::Struct, statsToStream}}, {IFLA_VF_PORTS, {"VF_PORTS"}}, {IFLA_PORT_SELF, {"PORT_SELF"}}, - {IFLA_AF_SPEC, {"AF_SPEC"}}, - {IFLA_GROUP, {"GROUP"}}, - {IFLA_NET_NS_FD, {"NET_NS_FD"}}, - {IFLA_EXT_MASK, {"EXT_MASK"}}, - {IFLA_PROMISCUITY, {"PROMISCUITY"}}, - {IFLA_NUM_TX_QUEUES, {"NUM_TX_QUEUES"}}, - {IFLA_NUM_RX_QUEUES, {"NUM_RX_QUEUES"}}, - {IFLA_CARRIER, {"CARRIER"}}, + {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"}}, + {IFLA_CARRIER_CHANGES, {"CARRIER_CHANGES", DataType::Uint}}, {IFLA_PHYS_SWITCH_ID, {"PHYS_SWITCH_ID"}}, - {IFLA_LINK_NETNSID, {"LINK_NETNSID"}}, - {IFLA_PHYS_PORT_NAME, {"PHYS_PORT_NAME"}}, - {IFLA_PROTO_DOWN, {"PROTO_DOWN"}}, - {IFLA_GSO_MAX_SEGS, {"GSO_MAX_SEGS"}}, - {IFLA_GSO_MAX_SIZE, {"GSO_MAX_SIZE"}}, + {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"}}, - {IFLA_NEW_NETNSID, {"NEW_NETNSID"}}, - {IFLA_TARGET_NETNSID, {"TARGET_NETNSID"}}, - {IFLA_CARRIER_UP_COUNT, {"CARRIER_UP_COUNT"}}, - {IFLA_CARRIER_DOWN_COUNT, {"CARRIER_DOWN_COUNT"}}, - {IFLA_NEW_IFINDEX, {"NEW_IFINDEX"}}, - {IFLA_MIN_MTU, {"MIN_MTU"}}, - {IFLA_MAX_MTU, {"MAX_MTU"}}, + {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"}}, + {IFLA_ALT_IFNAME, {"ALT_IFNAME", DataType::String}}, {IFLA_PERM_ADDRESS, {"PERM_ADDRESS"}}, }) {} // clang-format off diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/structs.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.cpp new file mode 100644 index 0000000000..48d64f0a4a --- /dev/null +++ b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 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 "structs.h" + +namespace android::netdevice::protocols::route { + +void mapToStream(std::stringstream& ss, const nlbuf attr) { + const auto& [ok, data] = attr.data().getFirst(); + if (!ok) { + ss << "invalid structure"; + return; + } + ss << '{' // + << data.mem_start << ',' // + << data.mem_end << ',' // + << data.base_addr << ',' // + << data.irq << ',' // + << unsigned(data.dma) << ',' // + << unsigned(data.port) << '}'; +} + +void ifla_cacheinfoToStream(std::stringstream& ss, const nlbuf attr) { + const auto& [ok, data] = attr.data().getFirst(); + if (!ok) { + ss << "invalid structure"; + return; + } + ss << '{' // + << data.max_reasm_len << ',' // + << data.tstamp << ',' // + << data.reachable_time << ',' // + << data.retrans_time << '}'; +} + +} // namespace android::netdevice::protocols::route diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/structs.h b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.h new file mode 100644 index 0000000000..e53270439c --- /dev/null +++ b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2020 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 + +#include + +#include + +namespace android::netdevice::protocols::route { + +// rtnl_link_ifmap +void mapToStream(std::stringstream& ss, const nlbuf attr); + +// ifla_cacheinfo +void ifla_cacheinfoToStream(std::stringstream& ss, const nlbuf attr); + +template +void arrayToStream(std::stringstream& ss, const nlbuf attr) { + ss << '{'; + for (const auto it : attr.data().getRaw()) { + ss << it << ','; + } + ss.seekp(-1, std::ios_base::cur); + ss << '}'; +} + +// rtnl_link_stats or rtnl_link_stats64 +template +void statsToStream(std::stringstream& ss, const nlbuf attr) { + const auto& [ok, data] = attr.data().getFirst(); + if (!ok) { + ss << "invalid structure"; + return; + } + ss << '{' // + << data.rx_packets << ',' // + << data.tx_packets << ',' // + << data.rx_bytes << ',' // + << data.tx_bytes << ',' // + << data.rx_errors << ',' // + << data.tx_errors << ',' // + << data.rx_dropped << ',' // + << data.tx_dropped << ',' // + << data.multicast << ',' // + << data.collisions << ',' // + << data.rx_length_errors << ',' // + << data.rx_over_errors << ',' // + << data.rx_crc_errors << ',' // + << data.rx_frame_errors << ',' // + << data.rx_fifo_errors << ',' // + << data.rx_missed_errors << ',' // + << data.tx_aborted_errors << ',' // + << data.tx_carrier_errors << ',' // + << data.tx_fifo_errors << ',' // + << data.tx_heartbeat_errors << ',' // + << data.tx_window_errors << ',' // + << data.rx_compressed << ',' // + << data.tx_compressed << ',' // + << data.rx_nohandler << '}'; +} + +} // namespace android::netdevice::protocols::route