Split out libnl++ from libnetdevice

Bug: 162032964
Test: it builds
Change-Id: I86b574de458d9ee8204e6a356a80e70c101b443a
diff --git a/automotive/can/1.0/default/libnetdevice/Android.bp b/automotive/can/1.0/default/libnetdevice/Android.bp
index d49b9ab..2605f88 100644
--- a/automotive/can/1.0/default/libnetdevice/Android.bp
+++ b/automotive/can/1.0/default/libnetdevice/Android.bp
@@ -18,29 +18,16 @@
     name: "android.hardware.automotive.can@libnetdevice",
     defaults: ["android.hardware.automotive.can@defaults"],
     vendor_available: true,
-    relative_install_path: "hw",
     srcs: [
-        "protocols/common/Empty.cpp",
-        "protocols/common/Error.cpp",
-        "protocols/generic/Ctrl.cpp",
-        "protocols/generic/Generic.cpp",
-        "protocols/generic/GenericMessageBase.cpp",
-        "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",
-        "NetlinkRequest.cpp",
-        "NetlinkSocket.cpp",
         "can.cpp",
         "common.cpp",
         "ethtool.cpp",
         "ifreqs.cpp",
         "libnetdevice.cpp",
-        "printer.cpp",
         "vlan.cpp",
     ],
     export_include_dirs: ["include"],
+    static_libs: [
+        "libnl++",
+    ],
 }
diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp b/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp
deleted file mode 100644
index 4c06f7c..0000000
--- a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2019 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 <libnetdevice/NetlinkRequest.h>
-
-#include <android-base/logging.h>
-
-namespace android::netdevice::impl {
-
-static struct rtattr* nlmsg_tail(struct nlmsghdr* n) {
-    return reinterpret_cast<struct rtattr*>(  //
-            reinterpret_cast<uintptr_t>(n) + NLMSG_ALIGN(n->nlmsg_len));
-}
-
-struct rtattr* addattr_l(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type, const void* data,
-                         size_t dataLen) {
-    size_t newLen = NLMSG_ALIGN(n->nlmsg_len) + RTA_SPACE(dataLen);
-    if (newLen > maxLen) {
-        LOG(ERROR) << "addattr_l failed - exceeded maxLen: " << newLen << " > " << maxLen;
-        return nullptr;
-    }
-
-    auto attr = nlmsg_tail(n);
-    attr->rta_len = RTA_SPACE(dataLen);
-    attr->rta_type = type;
-    if (dataLen > 0) memcpy(RTA_DATA(attr), data, dataLen);
-
-    n->nlmsg_len = newLen;
-    return attr;
-}
-
-struct rtattr* addattr_nest(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type) {
-    return addattr_l(n, maxLen, type, nullptr, 0);
-}
-
-void addattr_nest_end(struct nlmsghdr* n, struct rtattr* nest) {
-    size_t nestLen = reinterpret_cast<uintptr_t>(nlmsg_tail(n)) - reinterpret_cast<uintptr_t>(nest);
-    nest->rta_len = nestLen;
-}
-
-}  // namespace android::netdevice::impl
diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp b/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp
deleted file mode 100644
index 91149c0..0000000
--- a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2019 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 <libnetdevice/NetlinkSocket.h>
-
-#include <libnetdevice/printer.h>
-
-#include <android-base/logging.h>
-
-namespace android::netdevice {
-
-/**
- * Print all outbound/inbound Netlink messages.
- */
-static constexpr bool kSuperVerbose = false;
-
-NetlinkSocket::NetlinkSocket(int protocol, unsigned int pid, uint32_t groups)
-    : mProtocol(protocol) {
-    mFd.reset(socket(AF_NETLINK, SOCK_RAW, protocol));
-    if (!mFd.ok()) {
-        PLOG(ERROR) << "Can't open Netlink socket";
-        mFailed = true;
-        return;
-    }
-
-    sockaddr_nl sa = {};
-    sa.nl_family = AF_NETLINK;
-    sa.nl_pid = pid;
-    sa.nl_groups = groups;
-
-    if (bind(mFd.get(), reinterpret_cast<sockaddr*>(&sa), sizeof(sa)) < 0) {
-        PLOG(ERROR) << "Can't bind Netlink socket";
-        mFd.reset();
-        mFailed = true;
-    }
-}
-
-bool NetlinkSocket::send(nlmsghdr* nlmsg, size_t totalLen) {
-    if constexpr (kSuperVerbose) {
-        nlmsg->nlmsg_seq = mSeq;
-        LOG(VERBOSE) << (mFailed ? "(not) " : "")
-                     << "sending Netlink message: " << toString({nlmsg, totalLen}, mProtocol);
-    }
-
-    if (mFailed) return false;
-
-    nlmsg->nlmsg_pid = 0;  // kernel
-    nlmsg->nlmsg_seq = mSeq++;
-    nlmsg->nlmsg_flags |= NLM_F_ACK;
-
-    iovec iov = {nlmsg, nlmsg->nlmsg_len};
-
-    sockaddr_nl sa = {};
-    sa.nl_family = AF_NETLINK;
-
-    msghdr msg = {};
-    msg.msg_name = &sa;
-    msg.msg_namelen = sizeof(sa);
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-
-    if (sendmsg(mFd.get(), &msg, 0) < 0) {
-        PLOG(ERROR) << "Can't send Netlink message";
-        return false;
-    }
-    return true;
-}
-
-bool NetlinkSocket::send(const nlbuf<nlmsghdr>& msg, const sockaddr_nl& sa) {
-    if constexpr (kSuperVerbose) {
-        LOG(VERBOSE) << (mFailed ? "(not) " : "")
-                     << "sending Netlink message: " << toString(msg, mProtocol);
-    }
-
-    if (mFailed) return false;
-    const auto rawMsg = msg.getRaw();
-    const auto bytesSent = sendto(mFd.get(), rawMsg.ptr(), rawMsg.len(), 0,
-                                  reinterpret_cast<const sockaddr*>(&sa), sizeof(sa));
-    if (bytesSent < 0) {
-        PLOG(ERROR) << "Can't send Netlink message";
-        return false;
-    }
-    return true;
-}
-
-std::optional<nlbuf<nlmsghdr>> NetlinkSocket::receive(void* buf, size_t bufLen) {
-    sockaddr_nl sa = {};
-    return receive(buf, bufLen, sa);
-}
-
-std::optional<nlbuf<nlmsghdr>> NetlinkSocket::receive(void* buf, size_t bufLen, sockaddr_nl& sa) {
-    if (mFailed) return std::nullopt;
-
-    socklen_t saLen = sizeof(sa);
-    if (bufLen == 0) {
-        LOG(ERROR) << "Receive buffer has zero size!";
-        return std::nullopt;
-    }
-    const auto bytesReceived =
-            recvfrom(mFd.get(), buf, bufLen, MSG_TRUNC, reinterpret_cast<sockaddr*>(&sa), &saLen);
-    if (bytesReceived <= 0) {
-        PLOG(ERROR) << "Failed to receive Netlink message";
-        return std::nullopt;
-    } else if (unsigned(bytesReceived) > bufLen) {
-        PLOG(ERROR) << "Received data larger than the receive buffer! " << bytesReceived << " > "
-                    << bufLen;
-        return std::nullopt;
-    }
-
-    nlbuf<nlmsghdr> msg(reinterpret_cast<nlmsghdr*>(buf), bytesReceived);
-    if constexpr (kSuperVerbose) {
-        LOG(VERBOSE) << "received " << toString(msg, mProtocol);
-    }
-    return msg;
-}
-
-/* TODO(161389935): Migrate receiveAck to use nlmsg<> internally. Possibly reuse
- * NetlinkSocket::receive(). */
-bool NetlinkSocket::receiveAck() {
-    if (mFailed) return false;
-
-    char buf[8192];
-
-    sockaddr_nl sa;
-    iovec iov = {buf, sizeof(buf)};
-
-    msghdr msg = {};
-    msg.msg_name = &sa;
-    msg.msg_namelen = sizeof(sa);
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-
-    const ssize_t status = recvmsg(mFd.get(), &msg, 0);
-    if (status < 0) {
-        PLOG(ERROR) << "Failed to receive Netlink message";
-        return false;
-    }
-    size_t remainingLen = status;
-
-    if (msg.msg_flags & MSG_TRUNC) {
-        LOG(ERROR) << "Failed to receive Netlink message: truncated";
-        return false;
-    }
-
-    for (auto nlmsg = reinterpret_cast<nlmsghdr*>(buf); NLMSG_OK(nlmsg, remainingLen);
-         nlmsg = NLMSG_NEXT(nlmsg, remainingLen)) {
-        if constexpr (kSuperVerbose) {
-            LOG(VERBOSE) << "received Netlink response: "
-                         << toString({nlmsg, nlmsg->nlmsg_len}, mProtocol);
-        }
-
-        // We're looking for error/ack message only, ignoring others.
-        if (nlmsg->nlmsg_type != NLMSG_ERROR) {
-            LOG(WARNING) << "Received unexpected Netlink message (ignored): " << nlmsg->nlmsg_type;
-            continue;
-        }
-
-        // Found error/ack message, return status.
-        const auto nlerr = reinterpret_cast<nlmsgerr*>(NLMSG_DATA(nlmsg));
-        if (nlerr->error != 0) {
-            LOG(ERROR) << "Received Netlink error message: " << strerror(-nlerr->error);
-            return false;
-        }
-        return true;
-    }
-    // Couldn't find any error/ack messages.
-    return false;
-}
-
-std::optional<unsigned int> NetlinkSocket::getSocketPid() {
-    sockaddr_nl sa = {};
-    socklen_t sasize = sizeof(sa);
-    if (getsockname(mFd.get(), reinterpret_cast<sockaddr*>(&sa), &sasize) < 0) {
-        PLOG(ERROR) << "Failed to getsockname() for netlink_fd!";
-        return std::nullopt;
-    }
-    return sa.nl_pid;
-}
-
-}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/can.cpp b/automotive/can/1.0/default/libnetdevice/can.cpp
index b0a2432..fef9e00 100644
--- a/automotive/can/1.0/default/libnetdevice/can.cpp
+++ b/automotive/can/1.0/default/libnetdevice/can.cpp
@@ -20,8 +20,8 @@
 
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
-#include <libnetdevice/NetlinkRequest.h>
-#include <libnetdevice/NetlinkSocket.h>
+#include <libnl++/NetlinkRequest.h>
+#include <libnl++/NetlinkSocket.h>
 
 #include <linux/can.h>
 #include <linux/can/error.h>
diff --git a/automotive/can/1.0/default/libnetdevice/common.cpp b/automotive/can/1.0/default/libnetdevice/common.cpp
index f2968fc..28e50af 100644
--- a/automotive/can/1.0/default/libnetdevice/common.cpp
+++ b/automotive/can/1.0/default/libnetdevice/common.cpp
@@ -32,27 +32,4 @@
     return 0;
 }
 
-std::string sanitize(std::string str) {
-    str.erase(std::find(str.begin(), str.end(), '\0'), str.end());
-
-    const auto isInvalid = [](char c) { return !isprint(c); };
-    std::replace_if(str.begin(), str.end(), isInvalid, '?');
-
-    return str;
-}
-
-uint16_t crc16(const nlbuf<uint8_t> data, uint16_t crc) {
-    for (const auto byte : data.getRaw()) {
-        crc ^= byte;
-        for (unsigned i = 0; i < 8; i++) {
-            if (crc & 1) {
-                crc = (crc >> 1) ^ 0xA001;
-            } else {
-                crc >>= 1;
-            }
-        }
-    }
-    return crc;
-}
-
 }  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/common.h b/automotive/can/1.0/default/libnetdevice/common.h
index 1e0d5b7..201909f 100644
--- a/automotive/can/1.0/default/libnetdevice/common.h
+++ b/automotive/can/1.0/default/libnetdevice/common.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include <libnetdevice/nlbuf.h>
+#include <libnl++/nlbuf.h>
 
 #include <linux/can.h>
 #include <net/if.h>
@@ -36,24 +36,4 @@
  */
 unsigned int nametoindex(const std::string& ifname);
 
-/**
- * Sanitize a string of unknown contents.
- *
- * Trims the string to the first '\0' character and replaces all non-printable characters with '?'.
- */
-std::string sanitize(std::string str);
-
-/**
- * Calculates a (optionally running) CRC16 checksum.
- *
- * CRC16 isn't a strong checksum, but is good for quick comparison purposes.
- * One benefit (and also a drawback too) is that all-zero payloads with any length will
- * always have a checksum of 0x0000.
- *
- * \param data Buffer to calculate checksum for
- * \param crc Previous CRC16 value to continue calculating running checksum
- * \return CRC16 checksum
- */
-uint16_t crc16(const nlbuf<uint8_t> data, uint16_t crc = 0);
-
 }  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkRequest.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkRequest.h
deleted file mode 100644
index c19d04d..0000000
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkRequest.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2019 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 <android-base/macros.h>
-#include <libnetdevice/types.h>
-
-#include <linux/rtnetlink.h>
-
-#include <string>
-
-namespace android::netdevice {
-
-/** Implementation details, do not use outside NetlinkRequest template. */
-namespace impl {
-
-// TODO(twasilczyk): use nlattr instead of rtattr
-struct rtattr* addattr_l(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type, const void* data,
-                         size_t dataLen);
-struct rtattr* addattr_nest(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type);
-void addattr_nest_end(struct nlmsghdr* n, struct rtattr* nest);
-
-}  // namespace impl
-
-// TODO(twasilczyk): rename to NetlinkMessage
-/**
- * Wrapper around NETLINK_ROUTE messages, to build them in C++ style.
- *
- * \param T specific message header (such as struct ifinfomsg)
- * \param BUFSIZE how much space to reserve for payload (not counting the header size)
- */
-template <class T, unsigned int BUFSIZE = 128>
-struct NetlinkRequest {
-    struct RequestData {
-        struct nlmsghdr nlmsg;
-        T data;
-        char buf[BUFSIZE];
-    };
-
-    static constexpr size_t totalLength = sizeof(RequestData);
-
-    /**
-     * Create empty message.
-     *
-     * \param type Message type (such as RTM_NEWLINK)
-     * \param flags Message flags (such as NLM_F_REQUEST)
-     */
-    NetlinkRequest(nlmsgtype_t type, uint16_t flags) {
-        mRequest.nlmsg.nlmsg_len = NLMSG_LENGTH(sizeof(mRequest.data));
-        mRequest.nlmsg.nlmsg_type = type;
-        mRequest.nlmsg.nlmsg_flags = flags;
-    }
-
-    /** \return pointer to raw netlink message header. */
-    struct nlmsghdr* header() {
-        return &mRequest.nlmsg;
-    }
-    /** Reference to message-specific header. */
-    T& data() { return mRequest.data; }
-
-    /**
-     * Adds an attribute of a simple type.
-     *
-     * If this method fails (i.e. due to insufficient space), the message will be marked
-     * as bad (\see isGood).
-     *
-     * \param type attribute type (such as IFLA_IFNAME)
-     * \param attr attribute data
-     */
-    template <class A>
-    void addattr(rtattrtype_t type, const A& attr) {
-        if (!mIsGood) return;
-        auto ap = impl::addattr_l(&mRequest.nlmsg, sizeof(mRequest), type, &attr, sizeof(attr));
-        if (ap == nullptr) mIsGood = false;
-    }
-
-    template <>
-    void addattr(rtattrtype_t type, const std::string& s) {
-        if (!mIsGood) return;
-        auto ap = impl::addattr_l(&mRequest.nlmsg, sizeof(mRequest), type, s.c_str(), s.size() + 1);
-        if (ap == nullptr) mIsGood = false;
-    }
-
-    /** Guard class to frame nested attributes. See nest(int). */
-    struct Nest {
-        Nest(NetlinkRequest& req, rtattrtype_t type) : mReq(req), mAttr(req.nestStart(type)) {}
-        ~Nest() { mReq.nestEnd(mAttr); }
-
-      private:
-        NetlinkRequest& mReq;
-        struct rtattr* mAttr;
-
-        DISALLOW_COPY_AND_ASSIGN(Nest);
-    };
-
-    /**
-     * Add nested attribute.
-     *
-     * The returned object is a guard for auto-nesting children inside the argument attribute.
-     * When the Nest object goes out of scope, the nesting attribute is closed.
-     *
-     * Example usage nesting IFLA_CAN_BITTIMING inside IFLA_INFO_DATA, which is nested
-     * inside IFLA_LINKINFO:
-     *    NetlinkRequest<struct ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST);
-     *    {
-     *        auto linkinfo = req.nest(IFLA_LINKINFO);
-     *        req.addattr(IFLA_INFO_KIND, "can");
-     *        {
-     *            auto infodata = req.nest(IFLA_INFO_DATA);
-     *            req.addattr(IFLA_CAN_BITTIMING, bitTimingStruct);
-     *        }
-     *    }
-     *    // use req
-     *
-     * \param type attribute type (such as IFLA_LINKINFO)
-     */
-    Nest nest(int type) { return Nest(*this, type); }
-
-    /**
-     * Indicates, whether the message is in a good state.
-     *
-     * The bad state is usually a result of payload buffer being too small.
-     * You can modify BUFSIZE template parameter to fix this.
-     */
-    bool isGood() const { return mIsGood; }
-
-  private:
-    bool mIsGood = true;
-    RequestData mRequest = {};
-
-    struct rtattr* nestStart(rtattrtype_t type) {
-        if (!mIsGood) return nullptr;
-        auto attr = impl::addattr_nest(&mRequest.nlmsg, sizeof(mRequest), type);
-        if (attr == nullptr) mIsGood = false;
-        return attr;
-    }
-
-    void nestEnd(struct rtattr* nest) {
-        if (mIsGood && nest != nullptr) impl::addattr_nest_end(&mRequest.nlmsg, nest);
-    }
-};
-
-}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkSocket.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkSocket.h
deleted file mode 100644
index 826b6b8..0000000
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkSocket.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2019 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 <android-base/macros.h>
-#include <android-base/unique_fd.h>
-#include <libnetdevice/NetlinkRequest.h>
-#include <libnetdevice/nlbuf.h>
-
-#include <linux/netlink.h>
-
-#include <optional>
-
-namespace android::netdevice {
-
-/**
- * A wrapper around AF_NETLINK sockets.
- *
- * This class is not thread safe to use a single instance between multiple threads, but it's fine to
- * use multiple instances over multiple threads.
- */
-struct NetlinkSocket {
-    /**
-     * NetlinkSocket constructor.
-     *
-     * \param protocol the Netlink protocol to use.
-     * \param pid port id. Default value of 0 allows the kernel to assign us a unique pid. (NOTE:
-     * this is NOT the same as process id!)
-     * \param groups Netlink multicast groups to listen to. This is a 32-bit bitfield, where each
-     * bit is a different group. Default value of 0 means no groups are selected. See man netlink.7
-     * for more details.
-     */
-    NetlinkSocket(int protocol, unsigned int pid = 0, uint32_t groups = 0);
-
-    /**
-     * Send Netlink message to Kernel. The sequence number will be automatically incremented, and
-     * the NLM_F_ACK (request ACK) flag will be set.
-     *
-     * \param msg Message to send.
-     * \return true, if succeeded
-     */
-    template <class T, unsigned int BUFSIZE>
-    bool send(NetlinkRequest<T, BUFSIZE>& req) {
-        if (!req.isGood()) return false;
-        return send(req.header(), req.totalLength);
-    }
-
-    /**
-     * Send Netlink message. The message will be sent as is, without any modification.
-     *
-     * \param msg Message to send.
-     * \param sa Destination address.
-     * \return true, if succeeded
-     */
-    bool send(const nlbuf<nlmsghdr>& msg, const sockaddr_nl& sa);
-
-    /**
-     * Receive Netlink data.
-     *
-     * \param buf buffer to hold message data.
-     * \param bufLen length of buf.
-     * \return nlbuf with message data, std::nullopt on error.
-     */
-    std::optional<nlbuf<nlmsghdr>> receive(void* buf, size_t bufLen);
-
-    /**
-     * Receive Netlink data with address info.
-     *
-     * \param buf buffer to hold message data.
-     * \param bufLen length of buf.
-     * \param sa Blank struct that recvfrom will populate with address info.
-     * \return nlbuf with message data, std::nullopt on error.
-     */
-    std::optional<nlbuf<nlmsghdr>> receive(void* buf, size_t bufLen, sockaddr_nl& sa);
-
-    /**
-     * Receive Netlink ACK message from Kernel.
-     *
-     * \return true if received ACK message, false in case of error
-     */
-    bool receiveAck();
-
-    /**
-     * Gets the PID assigned to mFd.
-     *
-     * \return pid that mSocket is bound to.
-     */
-    std::optional<unsigned int> getSocketPid();
-
-  private:
-    const int mProtocol;
-
-    uint32_t mSeq = 0;
-    base::unique_fd mFd;
-    bool mFailed = false;
-
-    bool send(nlmsghdr* msg, size_t totalLen);
-
-    DISALLOW_COPY_AND_ASSIGN(NetlinkSocket);
-};
-
-}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h
deleted file mode 100644
index 601ab94..0000000
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * 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 <android-base/logging.h>
-
-#include <linux/netlink.h>
-
-#include <optional>
-
-namespace android::netdevice {
-
-/**
- * Buffer containing netlink structure (e.g. struct nlmsghdr, struct nlattr).
- *
- * This is a C++-style, memory safe(r) and generic implementation of linux/netlink.h macros.
- *
- * While netlink structures contain information about their total length (with payload), they can
- * not be trusted - the value may either be larger than the buffer message is allocated in or
- * smaller than the header itself (so it couldn't even fit itself).
- *
- * As a solution, nlbuf<> keeps track of two lengths (both attribute for header with payload):
- * - buffer length - how much memory was allocated to a given structure
- * - declared length - what nlmsg_len or nla_len says how long the structure is
- *
- * In most cases buffer length would be larger than declared length (or equal - modulo alignment -
- * for continuous data). If that's not the case, there is a potential of ouf-of-bounds read which
- * this template attempts to protect against.
- */
-template <typename T>
-class nlbuf {
-    // The following definitions are C++ equivalents of NLMSG_* macros from linux/netlink.h
-
-    static constexpr size_t alignto = NLMSG_ALIGNTO;
-    static_assert(NLMSG_ALIGNTO == NLA_ALIGNTO);
-
-    static constexpr size_t align(size_t ptr) { return (ptr + alignto - 1) & ~(alignto - 1); }
-
-    static constexpr size_t hdrlen = align(sizeof(T));
-
-  public:
-    /**
-     * Constructor for nlbuf.
-     *
-     * \param data A pointer to the data the nlbuf wraps.
-     * \param bufferLen Length of buffer.
-     */
-    nlbuf(const T* data, size_t bufferLen) : mData(data), mBufferEnd(pointerAdd(data, bufferLen)) {}
-
-    const T* operator->() const {
-        CHECK(firstOk()) << "buffer can't fit the first element's header";
-        return mData;
-    }
-
-    std::pair<bool, const T&> getFirst() const {
-        if (!ok()) {
-            static const T dummy = {};
-            return {false, dummy};
-        }
-        return {true, *mData};
-    }
-
-    /**
-     * Copy the first element of the buffer.
-     *
-     * This is a memory-safe cast operation, useful for reading e.g. uint32_t values
-     * from 1-byte buffer.
-     */
-    T copyFirst() const {
-        T val = {};
-        memcpy(&val, mData, std::min(sizeof(val), remainingLength()));
-        return val;
-    }
-
-    bool firstOk() const { return sizeof(T) <= remainingLength(); }
-
-    template <typename D>
-    const nlbuf<D> data(size_t offset = 0) const {
-        // Equivalent to NLMSG_DATA(hdr) + NLMSG_ALIGN(offset)
-        const D* dptr = reinterpret_cast<const D*>(uintptr_t(mData) + hdrlen + align(offset));
-        return {dptr, dataEnd()};
-    }
-
-    class iterator {
-      public:
-        iterator() : mCurrent(nullptr, size_t(0)) {
-            CHECK(!mCurrent.ok()) << "end() iterator should indicate it's beyond end";
-        }
-        iterator(const nlbuf<T>& buf) : mCurrent(buf) {}
-
-        iterator operator++() {
-            // mBufferEnd stays the same
-            mCurrent.mData = reinterpret_cast<const T*>(  //
-                    uintptr_t(mCurrent.mData) + align(mCurrent.declaredLength()));
-
-            return *this;
-        }
-
-        bool operator==(const iterator& other) const {
-            // all iterators beyond end are the same
-            if (!mCurrent.ok() && !other.mCurrent.ok()) return true;
-
-            return uintptr_t(other.mCurrent.mData) == uintptr_t(mCurrent.mData);
-        }
-
-        const nlbuf<T>& operator*() const { return mCurrent; }
-
-      protected:
-        nlbuf<T> mCurrent;
-    };
-    iterator begin() const { return {*this}; }
-    iterator end() const { return {}; }
-
-    class raw_iterator : public iterator {
-      public:
-        iterator operator++() {
-            this->mCurrent.mData++;  // ignore alignment
-            return *this;
-        }
-        const T& operator*() const { return *this->mCurrent.mData; }
-    };
-
-    class raw_view {
-      public:
-        raw_view(const nlbuf<T>& buffer) : mBuffer(buffer) {}
-        raw_iterator begin() const { return {mBuffer}; }
-        raw_iterator end() const { return {}; }
-
-        const T* ptr() const { return mBuffer.mData; }
-        size_t len() const { return mBuffer.remainingLength(); }
-
-      private:
-        const nlbuf<T> mBuffer;
-    };
-
-    raw_view getRaw() const { return {*this}; }
-
-  private:
-    const T* mData;
-    const void* mBufferEnd;
-
-    nlbuf(const T* data, const void* bufferEnd) : mData(data), mBufferEnd(bufferEnd) {}
-
-    bool ok() const { return declaredLength() <= remainingLength(); }
-
-    // to be specialized individually for each T with payload after a header
-    inline size_t declaredLengthImpl() const { return sizeof(T); }
-
-    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.
-        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 {
-        auto len = intptr_t(mBufferEnd) - intptr_t(mData);
-        return (len >= 0) ? len : 0;
-    }
-
-    const void* dataEnd() const {
-        auto declaredEnd = pointerAdd(mData, declaredLength());
-        return std::min(declaredEnd, mBufferEnd);
-    }
-
-    static const void* pointerAdd(const void* ptr, size_t len) {
-        return reinterpret_cast<const void*>(uintptr_t(ptr) + len);
-    }
-
-    template <typename D>
-    friend class nlbuf;  // calling private constructor of data buffers
-};
-
-template <>
-inline size_t nlbuf<nlmsghdr>::declaredLengthImpl() const {
-    return mData->nlmsg_len;
-}
-
-template <>
-inline size_t nlbuf<nlattr>::declaredLengthImpl() const {
-    return mData->nla_len;
-}
-
-}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/printer.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/printer.h
deleted file mode 100644
index 071fa63..0000000
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/printer.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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/netlink.h>
-
-#include <string>
-
-namespace android::netdevice {
-
-/**
- * Stringify a Netlink message.
- *
- * \param hdr Pointer to the message(s) to print.
- * \param protocol Which Netlink protocol hdr uses.
- * \param printPayload True will stringify message data, false will only stringify the header(s).
- * \return Stringified message.
- */
-std::string toString(const nlbuf<nlmsghdr> hdr, int protocol, bool printPayload = false);
-
-}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/types.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/types.h
deleted file mode 100644
index 9d90c8a..0000000
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/types.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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 <linux/types.h>
-
-namespace android::netdevice {
-
-typedef __u16 nlmsgtype_t;            // nlmsghdr::nlmsg_type
-typedef __u16 nlattrtype_t;           // nlattr::nla_type
-typedef unsigned short rtattrtype_t;  // rtattr::rta_type
-
-}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
index 4293cad..05d1e76 100644
--- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
+++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
@@ -20,8 +20,8 @@
 #include "ifreqs.h"
 
 #include <android-base/logging.h>
-#include <libnetdevice/NetlinkRequest.h>
-#include <libnetdevice/NetlinkSocket.h>
+#include <libnl++/NetlinkRequest.h>
+#include <libnl++/NetlinkSocket.h>
 
 #include <linux/can.h>
 #include <net/if.h>
diff --git a/automotive/can/1.0/default/libnetdevice/printer.cpp b/automotive/can/1.0/default/libnetdevice/printer.cpp
deleted file mode 100644
index 179d501..0000000
--- a/automotive/can/1.0/default/libnetdevice/printer.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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 <libnetdevice/printer.h>
-
-#include "common.h"
-#include "protocols/all.h"
-
-#include <android-base/logging.h>
-#include <libnetdevice/nlbuf.h>
-
-#include <algorithm>
-#include <iomanip>
-#include <sstream>
-
-namespace android::netdevice {
-
-static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags) {
-    bool first = true;
-    auto printFlag = [&ss, &first, &nlmsg_flags](__u16 flag, const std::string& name) {
-        if (!(nlmsg_flags & flag)) return;
-        nlmsg_flags &= ~flag;
-
-        if (first) {
-            first = false;
-        } else {
-            ss << '|';
-        }
-
-        ss << name;
-    };
-    printFlag(NLM_F_REQUEST, "REQUEST");
-    printFlag(NLM_F_MULTI, "MULTI");
-    printFlag(NLM_F_ACK, "ACK");
-    printFlag(NLM_F_ECHO, "ECHO");
-    printFlag(NLM_F_DUMP_INTR, "DUMP_INTR");
-    printFlag(NLM_F_DUMP_FILTERED, "DUMP_FILTERED");
-
-    // TODO(twasilczyk): print flags depending on request type
-    printFlag(NLM_F_ROOT, "ROOT-REPLACE");
-    printFlag(NLM_F_MATCH, "MATCH-EXCL");
-    printFlag(NLM_F_ATOMIC, "ATOMIC-CREATE");
-    printFlag(NLM_F_APPEND, "APPEND");
-
-    if (nlmsg_flags != 0) {
-        if (!first) ss << '|';
-        ss << std::hex << nlmsg_flags << std::dec;
-    }
-}
-
-static void toStream(std::stringstream& ss, const nlbuf<uint8_t> data) {
-    const auto rawData = data.getRaw();
-    const auto dataLen = rawData.len();
-    ss << std::hex;
-    int i = 0;
-    for (const auto byte : rawData) {
-        if (i % 16 == 0 && dataLen > 16) {
-            ss << std::endl << ' ' << std::dec << std::setw(4) << i << std::hex;
-        }
-        if (i++ > 0 || dataLen > 16) ss << ' ';
-        ss << std::setw(2) << unsigned(byte);
-    }
-    ss << std::dec;
-    if (dataLen > 16) ss << std::endl;
-}
-
-static void toStream(std::stringstream& ss, const nlbuf<nlattr> attr,
-                     const protocols::AttributeMap& attrMap) {
-    using DataType = protocols::AttributeDefinition::DataType;
-    const auto attrtype = attrMap[attr->nla_type];
-
-    ss << attrtype.name << ": ";
-    switch (attrtype.dataType) {
-        case DataType::Raw:
-            toStream(ss, attr.data<uint8_t>());
-            break;
-        case DataType::Nested: {
-            ss << '{';
-            bool first = true;
-            for (const auto childattr : attr.data<nlattr>()) {
-                if (!first) ss << ", ";
-                first = false;
-                toStream(ss, childattr, std::get<protocols::AttributeMap>(attrtype.ops));
-            }
-            ss << '}';
-            break;
-        }
-        case DataType::String: {
-            const auto str = attr.data<char>().getRaw();
-            ss << '"' << sanitize({str.ptr(), str.len()}) << '"';
-            break;
-        }
-        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;
-        }
-    }
-}
-
-std::string toString(const nlbuf<nlmsghdr> hdr, int protocol, bool printPayload) {
-    if (!hdr.firstOk()) return "nlmsg{buffer overflow}";
-
-    std::stringstream ss;
-    ss << std::setfill('0');
-
-    auto protocolMaybe = protocols::get(protocol);
-    if (!protocolMaybe.has_value()) {
-        ss << "nlmsg{protocol=" << protocol << "}";
-        return ss.str();
-    }
-    protocols::NetlinkProtocol& protocolDescr = *protocolMaybe;
-
-    auto msgDescMaybe = protocolDescr.getMessageDescriptor(hdr->nlmsg_type);
-    const auto msgTypeName = msgDescMaybe.has_value()
-                                     ? msgDescMaybe->get().getMessageName(hdr->nlmsg_type)
-                                     : std::to_string(hdr->nlmsg_type);
-
-    ss << "nlmsg{" << protocolDescr.getName() << " ";
-
-    ss << "hdr={";
-    ss << "type=" << msgTypeName;
-    if (hdr->nlmsg_flags != 0) {
-        ss << ", flags=";
-        flagsToStream(ss, hdr->nlmsg_flags);
-    }
-    if (hdr->nlmsg_seq != 0) ss << ", seq=" << hdr->nlmsg_seq;
-    if (hdr->nlmsg_pid != 0) ss << ", pid=" << hdr->nlmsg_pid;
-    ss << ", len=" << hdr->nlmsg_len;
-
-    ss << ", crc=" << std::hex << std::setw(4) << crc16(hdr.data<uint8_t>()) << std::dec;
-    ss << "} ";
-
-    if (!printPayload) return ss.str();
-
-    if (!msgDescMaybe.has_value()) {
-        toStream(ss, hdr.data<uint8_t>());
-    } else {
-        const protocols::MessageDescriptor& msgDesc = *msgDescMaybe;
-        msgDesc.dataToStream(ss, hdr);
-
-        bool first = true;
-        for (auto attr : hdr.data<nlattr>(msgDesc.getContentsSize())) {
-            if (first) {
-                ss << " attributes: {";
-                first = false;
-            } else {
-                ss << ", ";
-            }
-            toStream(ss, attr, msgDesc.getAttributeMap());
-        }
-        if (!first) ss << '}';
-    }
-
-    ss << "}";
-
-    return ss.str();
-}
-
-}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.cpp b/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.cpp
deleted file mode 100644
index cb42896..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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 "MessageDefinition.h"
-
-namespace android::netdevice::protocols {
-
-AttributeMap::AttributeMap(const std::initializer_list<value_type> attrTypes)
-    : std::map<std::optional<nlattrtype_t>, AttributeDefinition>(attrTypes) {}
-
-const AttributeDefinition AttributeMap::operator[](nlattrtype_t nla_type) const {
-    if (count(nla_type) == 0) {
-        if (count(std::nullopt) == 0) return {std::to_string(nla_type)};
-
-        auto definition = find(std::nullopt)->second;
-        definition.name += std::to_string(nla_type);
-        return definition;
-    }
-    return find(nla_type)->second;
-}
-
-MessageDescriptor::MessageDescriptor(const std::string& name, const MessageTypeMap&& messageTypes,
-                                     const AttributeMap&& attrTypes, size_t contentsSize)
-    : mName(name),
-      mContentsSize(contentsSize),
-      mMessageTypes(messageTypes),
-      mAttributeMap(attrTypes) {}
-
-MessageDescriptor::~MessageDescriptor() {}
-
-size_t MessageDescriptor::getContentsSize() const {
-    return mContentsSize;
-}
-
-const MessageDescriptor::MessageTypeMap& MessageDescriptor::getMessageTypeMap() const {
-    return mMessageTypes;
-}
-
-const AttributeMap& MessageDescriptor::getAttributeMap() const {
-    return mAttributeMap;
-}
-
-const std::string MessageDescriptor::getMessageName(nlmsgtype_t msgtype) const {
-    const auto it = mMessageTypes.find(msgtype);
-    if (it == mMessageTypes.end()) return "?";
-    return it->second;
-}
-
-}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h b/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h
deleted file mode 100644
index 3a8b2b5..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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 <libnetdevice/types.h>
-
-#include <map>
-#include <sstream>
-#include <variant>
-
-namespace android::netdevice::protocols {
-
-struct AttributeDefinition;
-
-/**
- * Mapping between nlattrtype_t identifier and attribute definition.
- *
- * The map contains values for all nlattrtype_t identifiers - if some is missing, a generic
- * definition with a identifier as its name will be generated.
- *
- * It's possible to define a default attribute to return instead of to_string of its identifier
- * (useful for nested attribute lists). In such case, an entry with id=std::nullopt needs to be
- * present in the map.
- */
-class AttributeMap : private std::map<std::optional<nlattrtype_t>, AttributeDefinition> {
-  public:
-    using std::map<std::optional<nlattrtype_t>, AttributeDefinition>::value_type;
-
-    AttributeMap(const std::initializer_list<value_type> attrTypes);
-
-    const AttributeDefinition operator[](nlattrtype_t nla_type) const;
-};
-
-/**
- * Attribute definition.
- *
- * Describes the name and type (optionally sub types, in case of Nested attribute)
- * for a given message attribute.
- */
-struct AttributeDefinition {
-    enum class DataType : uint8_t {
-        Raw,
-        Nested,
-        String,
-        Uint,
-        Struct,
-    };
-    using ToStream = std::function<void(std::stringstream& ss, const nlbuf<nlattr> attr)>;
-
-    std::string name;
-    DataType dataType = DataType::Raw;
-    std::variant<AttributeMap, ToStream> ops = AttributeMap{};
-};
-
-/**
- * Message family descriptor.
- *
- * Describes the structure of all message types with the same header and attributes.
- */
-class MessageDescriptor {
-  protected:
-    typedef std::map<nlmsgtype_t, std::string> MessageTypeMap;
-
-    MessageDescriptor(const std::string& name, const MessageTypeMap&& messageTypes,
-                      const AttributeMap&& attrTypes, size_t contentsSize);
-
-  public:
-    virtual ~MessageDescriptor();
-
-    size_t getContentsSize() const;
-    const MessageTypeMap& getMessageTypeMap() const;
-    const AttributeMap& getAttributeMap() const;
-    const std::string getMessageName(nlmsgtype_t msgtype) const;
-    virtual void dataToStream(std::stringstream& ss, const nlbuf<nlmsghdr> hdr) const = 0;
-
-  private:
-    const std::string mName;
-    const size_t mContentsSize;
-    const MessageTypeMap mMessageTypes;
-    const AttributeMap mAttributeMap;
-};
-
-/**
- * Message definition template.
- *
- * A convenience initialization helper of a message descriptor.
- */
-template <typename T>
-class MessageDefinition : public MessageDescriptor {
-  public:
-    MessageDefinition(
-            const std::string& name,
-            const std::initializer_list<MessageDescriptor::MessageTypeMap::value_type> messageTypes,
-            const std::initializer_list<AttributeMap::value_type> attrTypes = {})
-        : MessageDescriptor(name, messageTypes, attrTypes, sizeof(T)) {}
-
-    void dataToStream(std::stringstream& ss, const nlbuf<nlmsghdr> hdr) const override {
-        const auto& [ok, msg] = hdr.data<T>().getFirst();
-        if (!ok) {
-            ss << "{incomplete payload}";
-            return;
-        }
-
-        toStream(ss, msg);
-    }
-
-  protected:
-    virtual void toStream(std::stringstream& ss, const T& data) const = 0;
-};
-
-}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.cpp b/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.cpp
deleted file mode 100644
index 4b6cefb..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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 "NetlinkProtocol.h"
-
-namespace android::netdevice::protocols {
-
-NetlinkProtocol::NetlinkProtocol(int protocol, const std::string name,
-                                 const MessageDescriptorList&& messageDescrs)
-    : mProtocol(protocol), mName(name), mMessageDescrs(toMap(messageDescrs, protocol)) {}
-
-NetlinkProtocol::~NetlinkProtocol() {}
-
-int NetlinkProtocol::getProtocol() const {
-    return mProtocol;
-}
-
-const std::string& NetlinkProtocol::getName() const {
-    return mName;
-}
-
-const std::optional<std::reference_wrapper<const MessageDescriptor>>
-NetlinkProtocol::getMessageDescriptor(nlmsgtype_t nlmsg_type) {
-    if (mMessageDescrs.count(nlmsg_type) == 0) return std::nullopt;
-    return *mMessageDescrs.find(nlmsg_type)->second;
-}
-
-NetlinkProtocol::MessageDescriptorMap NetlinkProtocol::toMap(
-        const NetlinkProtocol::MessageDescriptorList& descrs, int protocol) {
-    MessageDescriptorMap map;
-    for (const auto& descr : descrs) {
-        for (const auto& [mtype, mname] : descr->getMessageTypeMap()) {
-            map.emplace(mtype, descr);
-        }
-    }
-
-    const MessageDescriptorList baseDescriptors = {
-            std::make_shared<base::Empty>(),
-            std::make_shared<base::Error>(protocol),
-    };
-
-    for (const auto& descr : baseDescriptors) {
-        for (const auto& [mtype, mname] : descr->getMessageTypeMap()) {
-            map.emplace(mtype, descr);
-        }
-    }
-
-    return map;
-}
-
-}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.h b/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.h
deleted file mode 100644
index 7b12efa..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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 "MessageDefinition.h"
-#include "common/Empty.h"
-#include "common/Error.h"
-
-#include <libnetdevice/types.h>
-
-#include <string>
-#include <vector>
-
-namespace android::netdevice::protocols {
-
-/**
- * Netlink-based protocol definition.
- *
- * Usually it's just an id/name and a list of supported messages.
- */
-class NetlinkProtocol {
-  public:
-    virtual ~NetlinkProtocol();
-
-    int getProtocol() const;
-
-    const std::string& getName() const;
-
-    virtual const std::optional<std::reference_wrapper<const MessageDescriptor>>
-    getMessageDescriptor(nlmsgtype_t nlmsg_type);
-
-  protected:
-    typedef std::vector<std::shared_ptr<const MessageDescriptor>> MessageDescriptorList;
-
-    NetlinkProtocol(int protocol, const std::string name,
-                    const MessageDescriptorList&& messageDescrs);
-
-  private:
-    typedef std::map<nlmsgtype_t, std::shared_ptr<const MessageDescriptor>> MessageDescriptorMap;
-
-    const int mProtocol;
-    const std::string mName;
-    const MessageDescriptorMap mMessageDescrs;
-
-    static MessageDescriptorMap toMap(const MessageDescriptorList& descrs, int protocol);
-};
-
-}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/README b/automotive/can/1.0/default/libnetdevice/protocols/README
deleted file mode 100644
index 45c95c4..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/README
+++ /dev/null
@@ -1,8 +0,0 @@
-This folder contains message definitions for various protocols based on Netlink.
-
-The structure is as follows:
-protocols/*.(cpp|h)                - base definition classes and protocol definition lookup
-protocols/common/                  - common message types that apply to all protocols
-protocols/<proto>/<proto>.(cpp|h)  - protocol definition (usually just a list of message types)
-protocols/<proto>/*.(cpp|h)        - message definition that covers all message types with the same
-                                     header (T type in MessageDefinition template) and attributes
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/all.cpp b/automotive/can/1.0/default/libnetdevice/protocols/all.cpp
deleted file mode 100644
index 980e3d0..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/all.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 "all.h"
-
-#include "generic/Generic.h"
-#include "route/Route.h"
-
-#include <map>
-
-namespace android::netdevice::protocols {
-
-// This should be a map of unique_ptr, but it's not trivial to uniformly initialize such a map
-static std::map<int, std::shared_ptr<NetlinkProtocol>> toMap(
-        std::initializer_list<std::shared_ptr<NetlinkProtocol>> l) {
-    std::map<int, std::shared_ptr<NetlinkProtocol>> map;
-    for (auto p : l) {
-        map[p->getProtocol()] = p;
-    }
-    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) {
-    if (all.count(protocol) == 0) return std::nullopt;
-    return *all.find(protocol)->second.get();
-}
-
-}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/all.h b/automotive/can/1.0/default/libnetdevice/protocols/all.h
deleted file mode 100644
index 2180ebb..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/all.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 "NetlinkProtocol.h"
-
-namespace android::netdevice::protocols {
-
-/**
- * Protocol definition lookup.
- *
- * \param protocol Protocol identifier from linux/netlink.h
- * \return Protocol definition or nullopt if it's not implemented
- */
-std::optional<std::reference_wrapper<NetlinkProtocol>> get(int protocol);
-
-}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.cpp b/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.cpp
deleted file mode 100644
index 9f25203..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 "Empty.h"
-
-namespace android::netdevice::protocols::base {
-
-// clang-format off
-Empty::Empty() : MessageDefinition<char>("nlmsg", {
-    {NLMSG_NOOP, "NOOP"},
-    {NLMSG_DONE, "DONE"},
-    {NLMSG_OVERRUN, "OVERRUN"},
-}) {}
-// clang-format on
-
-void Empty::toStream(std::stringstream&, const char&) const {}
-
-}  // namespace android::netdevice::protocols::base
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.h b/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.h
deleted file mode 100644
index b5b317f..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 "../MessageDefinition.h"
-
-#include <libnetdevice/printer.h>
-
-namespace android::netdevice::protocols::base {
-
-// no-payload (like NLMSG_NOOP) messages can't be defined with T=void, so let's use char
-class Empty : public MessageDefinition<char> {
-  public:
-    Empty();
-    void toStream(std::stringstream&, const char&) const override;
-};
-
-}  // namespace android::netdevice::protocols::base
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/common/Error.cpp b/automotive/can/1.0/default/libnetdevice/protocols/common/Error.cpp
deleted file mode 100644
index 25ae680..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/common/Error.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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 "Error.h"
-
-#include "../MessageDefinition.h"
-
-#include <libnetdevice/printer.h>
-
-namespace android::netdevice::protocols::base {
-
-// clang-format off
-Error::Error(int protocol) : MessageDefinition<nlmsgerr>("nlmsg", {
-    {NLMSG_ERROR, "ERROR"},
-}), mProtocol(protocol) {}
-// clang-format on
-
-void Error::toStream(std::stringstream& ss, const nlmsgerr& data) const {
-    ss << "nlmsgerr{error=" << data.error
-       << ", msg=" << toString({&data.msg, sizeof(data.msg)}, mProtocol) << "}";
-}
-
-}  // namespace android::netdevice::protocols::base
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/common/Error.h b/automotive/can/1.0/default/libnetdevice/protocols/common/Error.h
deleted file mode 100644
index 1f3c1dd..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/common/Error.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 "../MessageDefinition.h"
-
-namespace android::netdevice::protocols::base {
-
-class Error : public MessageDefinition<nlmsgerr> {
-  public:
-    Error(int protocol);
-    void toStream(std::stringstream& ss, const nlmsgerr& data) const override;
-
-  private:
-    const int mProtocol;
-};
-
-}  // namespace android::netdevice::protocols::base
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp
deleted file mode 100644
index 4120008..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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 "Ctrl.h"
-
-namespace android::netdevice::protocols::generic {
-
-using DataType = AttributeDefinition::DataType;
-
-// clang-format off
-Ctrl::Ctrl() : GenericMessageBase(GENL_ID_CTRL, "ID_CTRL", {
-    {CTRL_CMD_NEWFAMILY, "NEWFAMILY"},
-    {CTRL_CMD_DELFAMILY, "DELFAMILY"},
-    {CTRL_CMD_GETFAMILY, "GETFAMILY"},
-    {CTRL_CMD_NEWOPS, "NEWOPS"},
-    {CTRL_CMD_DELOPS, "DELOPS"},
-    {CTRL_CMD_GETOPS, "GETOPS"},
-    {CTRL_CMD_NEWMCAST_GRP, "NEWMCAST_GRP"},
-    {CTRL_CMD_DELMCAST_GRP, "DELMCAST_GRP"},
-    {CTRL_CMD_GETMCAST_GRP, "GETMCAST_GRP"},
-}, {
-    {CTRL_ATTR_FAMILY_ID, {"FAMILY_ID", DataType::Uint}},
-    {CTRL_ATTR_FAMILY_NAME, {"FAMILY_NAME", DataType::String}},
-    {CTRL_ATTR_VERSION, {"VERSION", DataType::Uint}},
-    {CTRL_ATTR_HDRSIZE, {"HDRSIZE", DataType::Uint}},
-    {CTRL_ATTR_MAXATTR, {"MAXATTR", DataType::Uint}},
-    {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, AttributeMap{
-        {std::nullopt, {"GRP", DataType::Nested, AttributeMap{
-            {CTRL_ATTR_MCAST_GRP_NAME, {"NAME", DataType::String}},
-            {CTRL_ATTR_MCAST_GRP_ID, {"ID", DataType::Uint}},
-        }}},
-    }}},
-}) {}
-// clang-format on
-
-}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.h b/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.h
deleted file mode 100644
index 804ed2c..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 "GenericMessageBase.h"
-
-namespace android::netdevice::protocols::generic {
-
-class Ctrl : public GenericMessageBase {
-  public:
-    Ctrl();
-};
-
-}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.cpp
deleted file mode 100644
index 633ef3c..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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 "Generic.h"
-
-#include "Ctrl.h"
-#include "Unknown.h"
-
-namespace android::netdevice::protocols::generic {
-
-Generic::Generic() : NetlinkProtocol(NETLINK_GENERIC, "GENERIC", {std::make_shared<Ctrl>()}) {}
-
-const std::optional<std::reference_wrapper<const MessageDescriptor>> Generic::getMessageDescriptor(
-        nlmsgtype_t nlmsg_type) {
-    const auto desc = NetlinkProtocol::getMessageDescriptor(nlmsg_type);
-    if (desc.has_value()) return desc;
-
-    auto it = mFamilyRegister.find(nlmsg_type);
-    if (it != mFamilyRegister.end()) return *it->second;
-    return *(mFamilyRegister[nlmsg_type] = std::make_shared<Unknown>(nlmsg_type));
-}
-
-}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.h b/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.h
deleted file mode 100644
index b4352f6..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 "../NetlinkProtocol.h"
-
-namespace android::netdevice::protocols::generic {
-
-/**
- * Definition of NETLINK_GENERIC protocol.
- */
-class Generic : public NetlinkProtocol {
-  public:
-    Generic();
-
-    const std::optional<std::reference_wrapper<const MessageDescriptor>> getMessageDescriptor(
-            nlmsgtype_t nlmsg_type);
-
-  private:
-    std::map<nlmsgtype_t, std::shared_ptr<const MessageDescriptor>> mFamilyRegister;
-};
-
-}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.cpp
deleted file mode 100644
index c9f0813..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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 "GenericMessageBase.h"
-
-namespace android::netdevice::protocols::generic {
-
-GenericMessageBase::GenericMessageBase(
-        nlmsgtype_t msgtype, std::string msgname,
-        const std::initializer_list<GenericCommandNameMap::value_type> commandNames,
-        const std::initializer_list<AttributeMap::value_type> attrTypes)
-    : MessageDefinition<struct genlmsghdr>(msgname, {{msgtype, msgname}}, attrTypes),
-      mCommandNames(commandNames) {}
-
-void GenericMessageBase::toStream(std::stringstream& ss, const struct genlmsghdr& data) const {
-    ss << "genlmsghdr{";
-    if (mCommandNames.count(data.cmd) == 0) {
-        ss << "cmd=" << unsigned(data.cmd);
-    } else {
-        ss << "cmd=" << mCommandNames.find(data.cmd)->second;
-    }
-    ss << ", version=" << unsigned(data.version);
-    if (data.reserved != 0) ss << ", reserved=" << data.reserved;
-    ss << "}";
-}
-
-}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.h b/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.h
deleted file mode 100644
index 2a19034..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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 "../MessageDefinition.h"
-
-#include <linux/genetlink.h>
-
-namespace android::netdevice::protocols::generic {
-
-class GenericMessageBase : public MessageDefinition<struct genlmsghdr> {
-  public:
-    typedef std::map<uint8_t, std::string> GenericCommandNameMap;
-
-    GenericMessageBase(
-            nlmsgtype_t msgtype, std::string msgname,
-            const std::initializer_list<GenericCommandNameMap::value_type> commandNames = {},
-            const std::initializer_list<AttributeMap::value_type> attrTypes = {});
-
-    void toStream(std::stringstream& ss, const struct genlmsghdr& data) const override;
-
-  private:
-    const GenericCommandNameMap mCommandNames;
-};
-
-}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.cpp
deleted file mode 100644
index 9a71d89..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 "Unknown.h"
-
-namespace android::netdevice::protocols::generic {
-
-Unknown::Unknown(nlmsgtype_t msgtype)
-    : GenericMessageBase(msgtype, "Unknown(" + std::to_string(msgtype) + ")") {}
-
-}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.h b/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.h
deleted file mode 100644
index 82a5501..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 "GenericMessageBase.h"
-
-namespace android::netdevice::protocols::generic {
-
-class Unknown : public GenericMessageBase {
-  public:
-    Unknown(nlmsgtype_t msgtype);
-};
-
-}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp
deleted file mode 100644
index 53e1700..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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 "Link.h"
-
-#include "structs.h"
-
-#include <net/if.h>
-
-namespace android::netdevice::protocols::route {
-
-using DataType = AttributeDefinition::DataType;
-
-// clang-format off
-Link::Link() : MessageDefinition<struct ifinfomsg>("link", {
-    {RTM_NEWLINK, "NEWLINK"},
-    {RTM_DELLINK, "DELLINK"},
-    {RTM_GETLINK, "GETLINK"},
-}, {
-    {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
-
-void Link::toStream(std::stringstream& ss, const struct ifinfomsg& data) const {
-    ss << "ifinfomsg{"
-       << "family=" << unsigned(data.ifi_family) << ", type=" << data.ifi_type
-       << ", index=" << data.ifi_index << ", flags=" << data.ifi_flags
-       << ", change=" << data.ifi_change << "}";
-}
-
-}  // namespace android::netdevice::protocols::route
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/Link.h b/automotive/can/1.0/default/libnetdevice/protocols/route/Link.h
deleted file mode 100644
index bcfce19..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/route/Link.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 "../MessageDefinition.h"
-
-#include <linux/rtnetlink.h>
-
-namespace android::netdevice::protocols::route {
-
-class Link : public MessageDefinition<struct ifinfomsg> {
-  public:
-    Link();
-    void toStream(std::stringstream& ss, const struct ifinfomsg& data) const override;
-};
-
-}  // namespace android::netdevice::protocols::route
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/Route.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/Route.cpp
deleted file mode 100644
index 456072b..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/route/Route.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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 "Route.h"
-
-#include "Link.h"
-
-namespace android::netdevice::protocols::route {
-
-Route::Route() : NetlinkProtocol(NETLINK_ROUTE, "ROUTE", {std::make_shared<Link>()}) {}
-
-}  // namespace android::netdevice::protocols::route
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/Route.h b/automotive/can/1.0/default/libnetdevice/protocols/route/Route.h
deleted file mode 100644
index 3051cf9..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/route/Route.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 "../NetlinkProtocol.h"
-
-namespace android::netdevice::protocols::route {
-
-/**
- * Definition of NETLINK_ROUTE protocol.
- */
-class Route : public NetlinkProtocol {
-  public:
-    Route();
-};
-
-}  // namespace android::netdevice::protocols::route
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/structs.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.cpp
deleted file mode 100644
index 48d64f0..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/route/structs.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/structs.h b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.h
deleted file mode 100644
index e532704..0000000
--- a/automotive/can/1.0/default/libnetdevice/protocols/route/structs.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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
diff --git a/automotive/can/1.0/default/libnetdevice/vlan.cpp b/automotive/can/1.0/default/libnetdevice/vlan.cpp
index f0caacd..3c70247 100644
--- a/automotive/can/1.0/default/libnetdevice/vlan.cpp
+++ b/automotive/can/1.0/default/libnetdevice/vlan.cpp
@@ -19,8 +19,8 @@
 #include "common.h"
 
 #include <android-base/logging.h>
-#include <libnetdevice/NetlinkRequest.h>
-#include <libnetdevice/NetlinkSocket.h>
+#include <libnl++/NetlinkRequest.h>
+#include <libnl++/NetlinkSocket.h>
 
 namespace android::netdevice::vlan {