Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ab105b1 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk
Browse files

Refactor MessageFactory

While we're here, also drop struct keywords where we use Linux structures.

Bug: 162032964
Test: canhalctrl up test virtual vcan3
Change-Id: Ib629cad3d2203b998668f45534699292863cadd9
parent ec9c528a
Loading
Loading
Loading
Loading
+10 −11
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ namespace android::netdevice::can {
static constexpr can_err_mask_t kErrMask = CAN_ERR_MASK;

base::unique_fd socket(const std::string& ifname) {
    struct sockaddr_can addr = {};
    sockaddr_can addr = {};
    addr.can_family = AF_CAN;
    addr.can_ifindex = nametoindex(ifname);
    if (addr.can_ifindex == 0) {
@@ -58,7 +58,7 @@ base::unique_fd socket(const std::string& ifname) {
        return {};
    }

    if (0 != bind(sock.get(), reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) {
    if (0 != bind(sock.get(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) {
        LOG(ERROR) << "Can't bind to CAN interface " << ifname;
        return {};
    }
@@ -67,26 +67,25 @@ base::unique_fd socket(const std::string& ifname) {
}

bool setBitrate(std::string ifname, uint32_t bitrate) {
    struct can_bittiming bt = {};
    can_bittiming bt = {};
    bt.bitrate = bitrate;

    nl::MessageFactory<struct ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK);
    nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK);

    const auto ifidx = nametoindex(ifname);
    if (ifidx == 0) {
    req->ifi_index = nametoindex(ifname);
    if (req->ifi_index == 0) {
        LOG(ERROR) << "Can't find interface " << ifname;
        return false;
    }
    req.data().ifi_index = ifidx;

    {
        auto linkinfo = req.nest(IFLA_LINKINFO);
        req.addattr(IFLA_INFO_KIND, "can");
        auto linkinfo = req.addNested(IFLA_LINKINFO);
        req.add(IFLA_INFO_KIND, "can");
        {
            auto infodata = req.nest(IFLA_INFO_DATA);
            auto infodata = req.addNested(IFLA_INFO_DATA);
            /* For CAN FD, it would require to add IFLA_CAN_DATA_BITTIMING
             * and IFLA_CAN_CTRLMODE as well. */
            req.addattr(IFLA_CAN_BITTIMING, bt);
            req.add(IFLA_CAN_BITTIMING, bt);
        }
    }

+7 −7
Original line number Diff line number Diff line
@@ -62,13 +62,13 @@ bool down(std::string ifname) {
}

bool add(std::string dev, std::string type) {
    nl::MessageFactory<struct ifinfomsg> req(RTM_NEWLINK,
    nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK,
                                      NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
    req.addattr(IFLA_IFNAME, dev);
    req.add(IFLA_IFNAME, dev);

    {
        auto linkinfo = req.nest(IFLA_LINKINFO);
        req.addattr(IFLA_INFO_KIND, type);
        auto linkinfo = req.addNested(IFLA_LINKINFO);
        req.add(IFLA_INFO_KIND, type);
    }

    nl::Socket sock(NETLINK_ROUTE);
@@ -76,8 +76,8 @@ bool add(std::string dev, std::string type) {
}

bool del(std::string dev) {
    nl::MessageFactory<struct ifinfomsg> req(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK);
    req.addattr(IFLA_IFNAME, dev);
    nl::MessageFactory<ifinfomsg> req(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK);
    req.add(IFLA_IFNAME, dev);

    nl::Socket sock(NETLINK_ROUTE);
    return sock.send(req) && sock.receiveAck(req);
+8 −8
Original line number Diff line number Diff line
@@ -33,18 +33,18 @@ bool add(const std::string& eth, const std::string& vlan, uint16_t id) {
        return false;
    }

    nl::MessageFactory<struct ifinfomsg> req(RTM_NEWLINK,
    nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK,
                                      NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
    req.addattr(IFLA_IFNAME, vlan);
    req.addattr<uint32_t>(IFLA_LINK, ethidx);
    req.add(IFLA_IFNAME, vlan);
    req.add<uint32_t>(IFLA_LINK, ethidx);

    {
        auto linkinfo = req.nest(IFLA_LINKINFO);
        req.addattr(IFLA_INFO_KIND, "vlan");
        auto linkinfo = req.addNested(IFLA_LINKINFO);
        req.add(IFLA_INFO_KIND, "vlan");

        {
            auto linkinfo = req.nest(IFLA_INFO_DATA);
            req.addattr(IFLA_VLAN_ID, id);
            auto linkinfo = req.addNested(IFLA_INFO_DATA);
            req.add(IFLA_VLAN_ID, id);
        }
    }

+18 −23
Original line number Diff line number Diff line
@@ -17,41 +17,36 @@
#include <libnl++/MessageFactory.h>

#include <android-base/logging.h>
#include <libnl++/bits.h>

// for RTA_ macros missing from NLA_ definitions
#include <linux/rtnetlink.h>
namespace android::nl {

namespace android::nl::impl {

static struct nlattr* nlmsg_tail(struct nlmsghdr* n) {
    return reinterpret_cast<struct nlattr*>(  //
            reinterpret_cast<uintptr_t>(n) + NLMSG_ALIGN(n->nlmsg_len));
static nlattr* tail(nlmsghdr* msg) {
    return reinterpret_cast<nlattr*>(uintptr_t(msg) + impl::align(msg->nlmsg_len));
}

struct nlattr* addattr_l(struct nlmsghdr* n, size_t maxLen, nlattrtype_t type, const void* data,
nlattr* MessageFactoryBase::add(nlmsghdr* msg, size_t maxLen, nlattrtype_t type, const void* data,
                                size_t dataLen) {
    size_t newLen = NLMSG_ALIGN(n->nlmsg_len) + RTA_SPACE(dataLen);
    const auto totalAttrLen = impl::space<nlattr>(dataLen);
    const auto newLen = impl::align(msg->nlmsg_len) + totalAttrLen;
    if (newLen > maxLen) {
        LOG(ERROR) << "addattr_l failed - exceeded maxLen: " << newLen << " > " << maxLen;
        LOG(ERROR) << "Can't add attribute of size " << dataLen  //
                   << " - exceeded maxLen: " << newLen << " > " << maxLen;
        return nullptr;
    }

    auto attr = nlmsg_tail(n);
    attr->nla_len = RTA_SPACE(dataLen);
    auto attr = tail(msg);
    attr->nla_len = totalAttrLen;
    attr->nla_type = type;
    if (dataLen > 0) memcpy(RTA_DATA(attr), data, dataLen);
    if (dataLen > 0) memcpy(impl::data<nlattr, void>(attr), data, dataLen);

    n->nlmsg_len = newLen;
    msg->nlmsg_len = newLen;
    return attr;
}

struct nlattr* addattr_nest(struct nlmsghdr* n, size_t maxLen, nlattrtype_t type) {
    return addattr_l(n, maxLen, type, nullptr, 0);
}

void addattr_nest_end(struct nlmsghdr* n, struct nlattr* nest) {
    size_t nestLen = reinterpret_cast<uintptr_t>(nlmsg_tail(n)) - reinterpret_cast<uintptr_t>(nest);
    nest->nla_len = nestLen;
void MessageFactoryBase::closeNested(nlmsghdr* msg, nlattr* nested) {
    if (nested == nullptr) return;
    nested->nla_len = uintptr_t(tail(msg)) - uintptr_t(nested);
}

}  // namespace android::nl::impl
}  // namespace android::nl
+4 −14
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#pragma once

#include <android-base/logging.h>
#include <libnl++/bits.h>

#include <linux/netlink.h>

@@ -25,7 +26,7 @@
namespace android::nl {

/**
 * Buffer wrapper containing netlink structure (e.g. struct nlmsghdr, struct nlattr).
 * Buffer wrapper containing netlink structure (e.g. nlmsghdr, nlattr).
 *
 * This is a C++-style, memory safe(r) and generic implementation of linux/netlink.h macros.
 *
@@ -43,15 +44,6 @@ namespace android::nl {
 */
template <typename T>
class Buffer {
    // 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:
    /**
     * Constructs empty buffer of size 0.
@@ -96,9 +88,7 @@ class Buffer {

    template <typename D>
    const Buffer<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()};
        return {impl::data<const T, const D>(mData, offset), dataEnd()};
    }

    class iterator {
@@ -111,7 +101,7 @@ class Buffer {
        iterator operator++() {
            // mBufferEnd stays the same
            mCurrent.mData = reinterpret_cast<const T*>(  //
                    uintptr_t(mCurrent.mData) + align(mCurrent.declaredLength()));
                    uintptr_t(mCurrent.mData) + impl::align(mCurrent.declaredLength()));

            return *this;
        }
Loading