Merge "Implement struct printing"
This commit is contained in:
commit
1a925fc9ca
8 changed files with 217 additions and 57 deletions
|
@ -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",
|
||||
|
|
|
@ -66,9 +66,12 @@ class nlbuf {
|
|||
return mData;
|
||||
}
|
||||
|
||||
std::optional<std::reference_wrapper<const T>> getFirst() const {
|
||||
if (!ok()) return std::nullopt;
|
||||
return *mData;
|
||||
std::pair<bool, const T&> 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<T>& mBuffer;
|
||||
const nlbuf<T> 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<size_t>::max() / 2;
|
||||
return declaredLengthImpl();
|
||||
static constexpr size_t badHeaderLength = std::numeric_limits<size_t>::max() / 2;
|
||||
|
||||
if (sizeof(T) > remainingLength()) return badHeaderLength;
|
||||
const auto len = declaredLengthImpl();
|
||||
if (sizeof(T) > len) return badHeaderLength;
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t remainingLength() const {
|
||||
|
|
|
@ -85,17 +85,16 @@ static void toStream(std::stringstream& ss, const nlbuf<nlattr> attr,
|
|||
|
||||
ss << attrtype.name << ": ";
|
||||
switch (attrtype.dataType) {
|
||||
case DataType::Raw: {
|
||||
case DataType::Raw:
|
||||
toStream(ss, attr.data<uint8_t>());
|
||||
break;
|
||||
}
|
||||
case DataType::Nested: {
|
||||
ss << '{';
|
||||
bool first = true;
|
||||
for (auto childattr : attr.data<nlattr>()) {
|
||||
for (const auto childattr : attr.data<nlattr>()) {
|
||||
if (!first) ss << ", ";
|
||||
first = false;
|
||||
toStream(ss, childattr, attrtype.subTypes);
|
||||
toStream(ss, childattr, std::get<protocols::AttributeMap>(attrtype.ops));
|
||||
}
|
||||
ss << '}';
|
||||
break;
|
||||
|
@ -105,9 +104,14 @@ static void toStream(std::stringstream& ss, const nlbuf<nlattr> attr,
|
|||
ss << '"' << sanitize({str.ptr(), str.len()}) << '"';
|
||||
break;
|
||||
}
|
||||
case DataType::Uint: {
|
||||
case DataType::Uint:
|
||||
ss << attr.data<uint32_t>().copyFirst();
|
||||
break;
|
||||
case DataType::Struct: {
|
||||
const auto structToStream =
|
||||
std::get<protocols::AttributeDefinition::ToStream>(attrtype.ops);
|
||||
structToStream(ss, attr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
namespace android::netdevice::protocols {
|
||||
|
||||
|
@ -57,11 +58,13 @@ struct AttributeDefinition {
|
|||
Nested,
|
||||
String,
|
||||
Uint,
|
||||
Struct,
|
||||
};
|
||||
using ToStream = std::function<void(std::stringstream& ss, const nlbuf<nlattr> attr)>;
|
||||
|
||||
std::string name;
|
||||
DataType dataType = DataType::Raw;
|
||||
AttributeMap subTypes = {};
|
||||
std::variant<AttributeMap, ToStream> ops = AttributeMap{};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -107,13 +110,13 @@ class MessageDefinition : public MessageDescriptor {
|
|||
: MessageDescriptor(name, messageTypes, attrTypes, sizeof(T)) {}
|
||||
|
||||
void dataToStream(std::stringstream& ss, const nlbuf<nlmsghdr> hdr) const override {
|
||||
const auto msg = hdr.data<T>().getFirst();
|
||||
if (!msg.has_value()) {
|
||||
const auto& [ok, msg] = hdr.data<T>().getFirst();
|
||||
if (!ok) {
|
||||
ss << "{incomplete payload}";
|
||||
return;
|
||||
}
|
||||
|
||||
toStream(ss, *msg);
|
||||
toStream(ss, msg);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -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}},
|
||||
}}},
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
|
||||
#include "Link.h"
|
||||
|
||||
#include "structs.h"
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
namespace android::netdevice::protocols::route {
|
||||
|
||||
using DataType = AttributeDefinition::DataType;
|
||||
|
@ -29,62 +33,76 @@ Link::Link() : MessageDefinition<struct ifinfomsg>("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<rtnl_link_stats>}},
|
||||
{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<rtnl_link_stats64>}},
|
||||
{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<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"}},
|
||||
{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
|
||||
|
|
|
@ -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<nlattr> attr) {
|
||||
const auto& [ok, data] = attr.data<rtnl_link_ifmap>().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<nlattr> attr) {
|
||||
const auto& [ok, data] = attr.data<ifla_cacheinfo>().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
|
|
@ -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 <libnetdevice/nlbuf.h>
|
||||
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace android::netdevice::protocols::route {
|
||||
|
||||
// rtnl_link_ifmap
|
||||
void mapToStream(std::stringstream& ss, const nlbuf<nlattr> attr);
|
||||
|
||||
// ifla_cacheinfo
|
||||
void ifla_cacheinfoToStream(std::stringstream& ss, const nlbuf<nlattr> attr);
|
||||
|
||||
template <typename T>
|
||||
void arrayToStream(std::stringstream& ss, const nlbuf<nlattr> attr) {
|
||||
ss << '{';
|
||||
for (const auto it : attr.data<T>().getRaw()) {
|
||||
ss << it << ',';
|
||||
}
|
||||
ss.seekp(-1, std::ios_base::cur);
|
||||
ss << '}';
|
||||
}
|
||||
|
||||
// rtnl_link_stats or rtnl_link_stats64
|
||||
template <typename T>
|
||||
void statsToStream(std::stringstream& ss, const nlbuf<nlattr> attr) {
|
||||
const auto& [ok, data] = attr.data<T>().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
|
Loading…
Reference in a new issue