Flatten NetlinkRequest.

1. drop NetlinkRequest interface, as NR is a data structure,
2. drop RequestBuffer, as it is compatible with AutoFreeBuffer.

I hope the size of the CL won't discourage: it's essentially:
- collapsing two headers into one,
- replacing lots of '->' with '.'

Change-Id: I54a3f53215a20df4c3dbb48b11f1d84e03661620
diff --git a/common/libs/net/BUILD b/common/libs/net/BUILD
index 62f0f1f..79e7166 100644
--- a/common/libs/net/BUILD
+++ b/common/libs/net/BUILD
@@ -21,9 +21,9 @@
 )
 
 cc_test(
-    name = "netlink_client_test",
+    name = "netlink_request_test",
     size = "small",
-    srcs = ["netlink_client_test.cpp"],
+    srcs = ["netlink_request_test.cpp"],
     deps = [
         ":net",
         "//common/libs/glog:cuttlefish_logging",
diff --git a/common/libs/net/netlink_client.cpp b/common/libs/net/netlink_client.cpp
index 7948adc..0a09d86 100644
--- a/common/libs/net/netlink_client.cpp
+++ b/common/libs/net/netlink_client.cpp
@@ -33,7 +33,7 @@
   NetlinkClientImpl() = default;
   virtual ~NetlinkClientImpl() = default;
 
-  virtual bool Send(NetlinkRequest* message);
+  virtual bool Send(const NetlinkRequest& message);
 
   // Initialize NetlinkClient instance.
   // Open netlink channel and initialize interface list.
@@ -47,7 +47,6 @@
 
   SharedFD netlink_fd_;
   sockaddr_nl address_;
-  int seq_no_ = 0;
 };
 
 bool NetlinkClientImpl::CheckResponse(uint32_t seq_no) {
@@ -102,13 +101,11 @@
   return false;
 }
 
-bool NetlinkClientImpl::Send(NetlinkRequest* message) {
-  message->SetSeqNo(seq_no_++);
-
+bool NetlinkClientImpl::Send(const NetlinkRequest& message) {
   struct sockaddr_nl netlink_addr;
   struct iovec netlink_iov = {
-    message->RequestData(),
-    message->RequestLength()
+    message.RequestData(),
+    message.RequestLength()
   };
   struct msghdr msg;
   memset(&msg, 0, sizeof(msg));
@@ -126,7 +123,7 @@
     return false;
   }
 
-  return CheckResponse(message->SeqNo());
+  return CheckResponse(message.SeqNo());
 }
 
 bool NetlinkClientImpl::OpenNetlink(int type) {
diff --git a/common/libs/net/netlink_client.h b/common/libs/net/netlink_client.h
index 40c812a..7e2f385 100644
--- a/common/libs/net/netlink_client.h
+++ b/common/libs/net/netlink_client.h
@@ -30,7 +30,7 @@
   virtual ~NetlinkClient() {}
 
   // Send netlink message to kernel.
-  virtual bool Send(NetlinkRequest* message) = 0;
+  virtual bool Send(const NetlinkRequest& message) = 0;
 
  private:
   NetlinkClient(const NetlinkClient&);
diff --git a/common/libs/net/netlink_request.cpp b/common/libs/net/netlink_request.cpp
index 4156333..1c257ea 100644
--- a/common/libs/net/netlink_request.cpp
+++ b/common/libs/net/netlink_request.cpp
@@ -27,105 +27,32 @@
 
 namespace avd {
 namespace {
-// Representation of Network link request. Used to supply kernel with
-// information about which interface needs to be changed, and how.
-class NetlinkRequestImpl : public NetlinkRequest {
- public:
-  NetlinkRequestImpl(int32_t command, int32_t flags);
+uint32_t kRequestSequenceNumber = 0;
+}  // namespace
 
-  virtual void AddString(uint16_t type, const std::string& value) override;
-  virtual void AddInt32(uint16_t type, int32_t value) override;
-  virtual void AddInt8(uint16_t type, int8_t value) override;
-  virtual void AddAddrInfo(int32_t if_index) override;
-  virtual void AddIfInfo(int32_t if_index, bool operational) override;
-  virtual void PushList(uint16_t type) override;
-  virtual void PopList() override;
-  virtual void* RequestData() override;
-  virtual size_t RequestLength() override;
-  virtual uint32_t SeqNo() override {
-    return header_->nlmsg_seq;
-  }
-  virtual void SetSeqNo(uint32_t seq_no) override {
-    header_->nlmsg_seq = seq_no;
+uint32_t NetlinkRequest::SeqNo() const {
+  return header_->nlmsg_seq;
+}
+
+void* NetlinkRequest::AppendRaw(const void* data, size_t length) {
+  void* out = request_.end();
+
+  request_.Append(data, length);
+  int pad = RTA_ALIGN(length) - length;
+  if (pad > 0) {
+    request_.Resize(request_.size() + pad);
   }
 
-  void* AppendRaw(const void* data, size_t length) override {
-    return request_.AppendRaw(data, length);
-  }
+  return out;
+}
 
-  void* ReserveRaw(size_t length) override {
-    return request_.ReserveRaw(length);
-  }
+void* NetlinkRequest::ReserveRaw(size_t length) {
+  void* out = request_.end();
+  request_.Resize(request_.size() + RTA_ALIGN(length));
+  return out;
+}
 
- private:
-  class RequestBuffer {
-   public:
-    RequestBuffer()
-        : current_(0),
-          buffer_length_(512),
-          buffer_(new uint8_t[buffer_length_]) {}
-
-    ~RequestBuffer() {
-      delete[] buffer_;
-    }
-
-    void Resize(size_t new_length) {
-      // Replace old buffer with new one. This is not thread safe (and does not
-      // have to be).
-      new_length = RTA_ALIGN(new_length);
-      uint8_t* new_buffer = new uint8_t[new_length];
-
-      memcpy(new_buffer, buffer_, std::min(new_length, buffer_length_));
-      delete[] buffer_;
-
-      buffer_length_ = new_length;
-      buffer_ = new_buffer;
-    }
-
-    void* ReserveRaw(size_t length) {
-      // reserve new buffer with a bit of extra space, if needed.
-      if (length > (buffer_length_ - current_)) {
-        Resize(buffer_length_ + length + 64);
-      }
-
-      length = RTA_ALIGN(length);
-      uint8_t* out = &buffer_[current_];
-      memset(out, 0, length);
-      current_ += length;
-      return out;
-    }
-
-    void* AppendRaw(const void* data, size_t length) {
-      // reserve new buffer with a bit of extra space, if needed.
-      if (length > (buffer_length_ - current_)) {
-        Resize(buffer_length_ + length + 64);
-      }
-
-      uint8_t* out = &buffer_[current_];
-      memcpy(out, data, length);
-      memset(&out[length], 0, RTA_ALIGN(length) - length);
-      current_ += RTA_ALIGN(length);
-      return out;
-    }
-
-    size_t Length() {
-      return current_;
-    }
-
-   private:
-    size_t   current_;
-    size_t   buffer_length_;
-    uint8_t* buffer_;
-  };
-
-  nlattr* AppendTag(uint16_t type, const void* data, uint16_t length);
-
-  std::vector<std::pair<nlattr*, int32_t> > lists_;
-  RequestBuffer request_;
-  nlmsghdr* header_;
-};
-
-nlattr* NetlinkRequestImpl::AppendTag(
+nlattr* NetlinkRequest::AppendTag(
     uint16_t type, const void* data, uint16_t data_length) {
   nlattr* attr = Reserve<nlattr>();
   attr->nla_type = type;
@@ -134,27 +61,36 @@
   return attr;
 }
 
-NetlinkRequestImpl::NetlinkRequestImpl(
-    int32_t command, int32_t flags)
-    : header_(Reserve<nlmsghdr>()) {
+NetlinkRequest::NetlinkRequest(int32_t command, int32_t flags)
+    : request_(512),
+      header_(Reserve<nlmsghdr>()) {
+  flags |= NLM_F_ACK | NLM_F_REQUEST;
   header_->nlmsg_flags = flags;
   header_->nlmsg_type = command;
   header_->nlmsg_pid = getpid();
+  header_->nlmsg_seq = kRequestSequenceNumber++;
 }
 
-void NetlinkRequestImpl::AddString(uint16_t type, const std::string& value) {
+NetlinkRequest::NetlinkRequest(NetlinkRequest&& other) {
+  using std::swap;
+  swap(lists_, other.lists_);
+  swap(header_, other.header_);
+  request_.Swap(other.request_);
+}
+
+void NetlinkRequest::AddString(uint16_t type, const std::string& value) {
   AppendTag(type, value.c_str(), value.length() + 1);
 }
 
-void NetlinkRequestImpl::AddInt32(uint16_t type, int32_t value) {
+void NetlinkRequest::AddInt32(uint16_t type, int32_t value) {
   AppendTag(type, &value, sizeof(value));
 }
 
-void NetlinkRequestImpl::AddInt8(uint16_t type, int8_t value) {
+void NetlinkRequest::AddInt8(uint16_t type, int8_t value) {
   AppendTag(type, &value, sizeof(value));
 }
 
-void NetlinkRequestImpl::AddIfInfo(int32_t if_index, bool operational) {
+void NetlinkRequest::AddIfInfo(int32_t if_index, bool operational) {
   ifinfomsg* if_info = Reserve<ifinfomsg>();
   if_info->ifi_family = AF_UNSPEC;
   if_info->ifi_index = if_index;
@@ -162,7 +98,7 @@
   if_info->ifi_change = IFF_UP;
 }
 
-void NetlinkRequestImpl::AddAddrInfo(int32_t if_index) {
+void NetlinkRequest::AddAddrInfo(int32_t if_index) {
   ifaddrmsg* ad_info = Reserve<ifaddrmsg>();
   ad_info->ifa_family = AF_INET;
   ad_info->ifa_prefixlen = 24;
@@ -171,13 +107,13 @@
   ad_info->ifa_index = if_index;
 }
 
-void NetlinkRequestImpl::PushList(uint16_t type) {
-  int length = request_.Length();
+void NetlinkRequest::PushList(uint16_t type) {
+  int length = request_.size();
   nlattr* list = AppendTag(type, NULL, 0);
   lists_.push_back(std::make_pair(list, length));
 }
 
-void NetlinkRequestImpl::PopList() {
+void NetlinkRequest::PopList() {
   if (lists_.empty()) {
     LOG(ERROR) << "List pop with no lists left on stack.";
     return;
@@ -185,27 +121,17 @@
 
   std::pair<nlattr*, int> list = lists_.back();
   lists_.pop_back();
-  list.first->nla_len = request_.Length() - list.second;
+  list.first->nla_len = request_.size() - list.second;
 }
 
-void* NetlinkRequestImpl::RequestData() {
+void* NetlinkRequest::RequestData() const {
   // Update request length before reporting raw data.
-  header_->nlmsg_len = request_.Length();
+  header_->nlmsg_len = request_.size();
   return header_;
 }
 
-size_t NetlinkRequestImpl::RequestLength() {
-  return request_.Length();
-}
-}  // namespace
-
-std::unique_ptr<NetlinkRequest> NetlinkRequest::New(
-    int type, int flags) {
-  // Ensure we receive response.
-  flags |= NLM_F_ACK | NLM_F_REQUEST;
-
-  return std::unique_ptr<NetlinkRequest>(new NetlinkRequestImpl(
-      type, flags));
+size_t NetlinkRequest::RequestLength() const {
+  return request_.size();
 }
 
 }  // namespace avd
diff --git a/common/libs/net/netlink_request.h b/common/libs/net/netlink_request.h
index c50a1cc..0421795 100644
--- a/common/libs/net/netlink_request.h
+++ b/common/libs/net/netlink_request.h
@@ -16,9 +16,14 @@
 #ifndef COMMON_LIBS_NET_NETLINK_REQUEST_H_
 #define COMMON_LIBS_NET_NETLINK_REQUEST_H_
 
+#include <linux/netlink.h>
 #include <stddef.h>
+
 #include <memory>
 #include <string>
+#include <vector>
+
+#include "common/libs/auto_resources/auto_resources.h"
 
 namespace avd {
 // Abstraction of Network link request.
@@ -26,59 +31,61 @@
 // changed, and how.
 class NetlinkRequest {
  public:
-  NetlinkRequest() {}
-  virtual ~NetlinkRequest() {}
+  // Create new Netlink Request structure.
+  // Parameter |type| specifies netlink request type (eg. RTM_NEWLINK), while
+  // |flags| are netlink and request specific flags (eg. NLM_F_DUMP).
+  NetlinkRequest(int type, int flags);
+  NetlinkRequest(NetlinkRequest&& other);
+
+  ~NetlinkRequest() = default;
 
   // Add an IFLA tag followed by a string.
   // Returns true, if successful.
-  virtual void AddString(uint16_t type, const std::string& value) = 0;
+  void AddString(uint16_t type, const std::string& value);
 
   // Add an IFLA tag followed by int32.
   // Returns true, if successful.
-  virtual void AddInt32(uint16_t type, int32_t value) = 0;
+  void AddInt32(uint16_t type, int32_t value);
 
   // Add an IFLA tag followed by int8.
   // Returns true, if successful.
-  virtual void AddInt8(uint16_t type, int8_t value) = 0;
+  void AddInt8(uint16_t type, int8_t value);
 
   // Add an interface info structure.
   // Parameter |if_index| specifies particular interface index to which the
   // attributes following the IfInfo apply.
-  virtual void AddIfInfo(int32_t if_index, bool is_operational) = 0;
+  void AddIfInfo(int32_t if_index, bool is_operational);
 
   // Add an address info to a specific interface.
   // This method assumes the prefix length for address info is 24.
-  virtual void AddAddrInfo(int32_t if_index) = 0;
+  void AddAddrInfo(int32_t if_index);
 
   // Creates new list.
   // List mimmic recursive structures in a flat, contiuous representation.
   // Each call to PushList() should have a corresponding call to PopList
   // indicating end of sub-attribute list.
-  virtual void PushList(uint16_t type) = 0;
+  void PushList(uint16_t type);
 
   // Indicates end of previously declared list.
-  virtual void PopList() = 0;
+  void PopList();
 
   // Request data.
-  virtual void* RequestData() = 0;
+  void* RequestData() const;
 
   // Request length.
-  virtual size_t RequestLength() = 0;
-
-  // Set Sequence Number.
-  virtual void SetSeqNo(uint32_t seq_no) = 0;
+  size_t RequestLength() const;
 
   // Request Sequence Number.
-  virtual uint32_t SeqNo() = 0;
+  uint32_t SeqNo() const;
 
   // Append raw data to buffer.
   // data must not be null.
   // Returns pointer to copied location.
-  virtual void* AppendRaw(const void* data, size_t length) = 0;
+  void* AppendRaw(const void* data, size_t length);
 
   // Reserve |length| number of bytes in the buffer.
   // Returns pointer to reserved location.
-  virtual void* ReserveRaw(size_t length) = 0;
+  void* ReserveRaw(size_t length);
 
   // Append specialized data.
   template <typename T> T* Append(const T& data) {
@@ -90,14 +97,15 @@
     return static_cast<T*>(ReserveRaw(sizeof(T)));
   }
 
-  // Create new Netlink Request structure.
-  // Parameter |type| specifies netlink request type (eg. RTM_NEWLINK), while
-  // |flags| are netlink and request specific flags (eg. NLM_F_DUMP).
-  static std::unique_ptr<NetlinkRequest> New(int type, int flags);
-
  private:
-  NetlinkRequest(const NetlinkRequest&);
-  NetlinkRequest& operator= (const NetlinkRequest&);
+  nlattr* AppendTag(uint16_t type, const void* data, uint16_t length);
+
+  std::vector<std::pair<nlattr*, int32_t>> lists_;
+  AutoFreeBuffer request_;
+  nlmsghdr* header_;
+
+  NetlinkRequest(const NetlinkRequest&) = delete;
+  NetlinkRequest& operator= (const NetlinkRequest&) = delete;
 };
 }  // namespace avd
 #endif  // COMMON_LIBS_NET_NETLINK_REQUEST_H_
diff --git a/common/libs/net/netlink_client_test.cpp b/common/libs/net/netlink_request_test.cpp
similarity index 76%
rename from common/libs/net/netlink_client_test.cpp
rename to common/libs/net/netlink_request_test.cpp
index dbc4041..c39c624 100644
--- a/common/libs/net/netlink_client_test.cpp
+++ b/common/libs/net/netlink_request_test.cpp
@@ -19,6 +19,7 @@
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+#include <glog/logging.h>
 
 #include <iostream>
 #include <memory>
@@ -65,9 +66,9 @@
 // Matcher validating Netlink Request data.
 MATCHER_P2(RequestDataIs, data, length, "Matches expected request data") {
   size_t offset = sizeof(nlmsghdr);
-  if (offset + length != arg->RequestLength()) {
+  if (offset + length != arg.RequestLength()) {
     *result_listener << "Unexpected request length: "
-                     << arg->RequestLength() - offset << " vs " << length;
+                     << arg.RequestLength() - offset << " vs " << length;
     return false;
   }
 
@@ -75,15 +76,15 @@
   // call.
   const uint8_t* exp_data = static_cast<const uint8_t*>(
       static_cast<const void*>(data));
-  const uint8_t* act_data = static_cast<const uint8_t*>(arg->RequestData());
+  const uint8_t* act_data = static_cast<const uint8_t*>(arg.RequestData());
   return Compare(
       result_listener, exp_data, &act_data[offset], length);
 }
 
 MATCHER_P4(RequestHeaderIs, length, type, flags, seq,
            "Matches request header") {
-  nlmsghdr* header = static_cast<nlmsghdr*>(arg->RequestData());
-  if (arg->RequestLength() < sizeof(header)) {
+  nlmsghdr* header = static_cast<nlmsghdr*>(arg.RequestData());
+  if (arg.RequestLength() < sizeof(header)) {
     *result_listener << "Malformed header: too short.";
     return false;
   }
@@ -117,6 +118,9 @@
 }  // namespace
 
 class NetlinkClientTest : public ::testing::Test {
+  void SetUp() {
+    google::InstallFailureSignalHandler();
+  }
  protected:
   std::unique_ptr<NetlinkClient> nl_client_;
 };
@@ -134,9 +138,8 @@
 
   memcpy(&expected.text, kLongString, sizeof(kLongString));
 
-  auto request =
-      avd::NetlinkRequest::New(RTM_SETLINK, 0);
-  request->AddString(kDummyTag, kLongString);
+  avd::NetlinkRequest request(RTM_SETLINK, 0);
+  request.AddString(kDummyTag, kLongString);
   EXPECT_THAT(request, RequestDataIs(&expected, sizeof(expected)));
 }
 
@@ -151,9 +154,8 @@
     const uint32_t attr_value = kValue;
   } expected;
 
-  auto request =
-      avd::NetlinkRequest::New(RTM_SETLINK, 0);
-  request->AddInt32(kDummyTag, kValue);
+  avd::NetlinkRequest request(RTM_SETLINK, 0);
+  request.AddInt32(kDummyTag, kValue);
   EXPECT_THAT(request, RequestDataIs(&expected, sizeof(expected)));
 }
 
@@ -171,11 +173,10 @@
     const uint32_t attr_value = kValue;
   } expected;
 
-  auto request =
-      avd::NetlinkRequest::New(RTM_SETLINK, 0);
-  request->PushList(kListTag);
-  request->AddInt32(kDummyTag, kValue);
-  request->PopList();
+  avd::NetlinkRequest request(RTM_SETLINK, 0);
+  request.PushList(kListTag);
+  request.AddInt32(kDummyTag, kValue);
+  request.PopList();
 
   EXPECT_THAT(request, RequestDataIs(&expected, sizeof(expected)));
 }
@@ -197,13 +198,12 @@
     const uint32_t attr_value = kValue;
   } expected;
 
-  auto request =
-      avd::NetlinkRequest::New(RTM_SETLINK, 0);
-  request->PushList(kList1Tag);
-  request->PushList(kList2Tag);
-  request->AddInt32(kDummyTag, kValue);
-  request->PopList();
-  request->PopList();
+  avd::NetlinkRequest request(RTM_SETLINK, 0);
+  request.PushList(kList1Tag);
+  request.PushList(kList2Tag);
+  request.AddInt32(kDummyTag, kValue);
+  request.PopList();
+  request.PopList();
 
   EXPECT_THAT(request, RequestDataIs(&expected, sizeof(expected)));
 }
@@ -230,14 +230,13 @@
     const uint32_t attr2_value = kValue2;
   } expected;
 
-  auto request =
-      avd::NetlinkRequest::New(RTM_SETLINK, 0);
-  request->PushList(kList1Tag);
-  request->AddInt32(kDummy1Tag, kValue1);
-  request->PopList();
-  request->PushList(kList2Tag);
-  request->AddInt32(kDummy2Tag, kValue2);
-  request->PopList();
+  avd::NetlinkRequest request(RTM_SETLINK, 0);
+  request.PushList(kList1Tag);
+  request.AddInt32(kDummy1Tag, kValue1);
+  request.PopList();
+  request.PushList(kList2Tag);
+  request.AddInt32(kDummy2Tag, kValue2);
+  request.PopList();
 
   EXPECT_THAT(request, RequestDataIs(&expected, sizeof(expected)));
 }
@@ -264,48 +263,57 @@
     const uint32_t attr2_value = kValue2;
   } expected;
 
-  auto request =
-      avd::NetlinkRequest::New(RTM_SETLINK, 0);
-  request->PushList(kList1Tag);
-  request->PushList(kList2Tag);
-  request->AddInt32(kDummy1Tag, kValue1);
-  request->PopList();
-  request->AddInt32(kDummy2Tag, kValue2);
-  request->PopList();
+  avd::NetlinkRequest request(RTM_SETLINK, 0);
+  request.PushList(kList1Tag);
+  request.PushList(kList2Tag);
+  request.AddInt32(kDummy1Tag, kValue1);
+  request.PopList();
+  request.AddInt32(kDummy2Tag, kValue2);
+  request.PopList();
 
   EXPECT_THAT(request, RequestDataIs(&expected, sizeof(expected)));
 }
 
 TEST_F(NetlinkClientTest, SimpleNetlinkCreateHeader) {
-  auto request =
-      avd::NetlinkRequest::New(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
+  avd::NetlinkRequest request(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
   constexpr char kValue[] = "random string";
-  request->AddString(0, kValue);  // Have something to work with.
+  request.AddString(0, kValue);  // Have something to work with.
 
   constexpr size_t kMsgLength =
       sizeof(nlmsghdr) + sizeof(nlattr) + RTA_ALIGN(sizeof(kValue));
+  int base_seq = request.SeqNo();
 
   EXPECT_THAT(request, RequestHeaderIs(
-      kMsgLength,  // Expected size of message.
-      RTM_NEWLINK,  // Results from creane_new_iface=true in CreateRequest.
-      NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST,  // Ditto.
-      0u));
+      kMsgLength,
+      RTM_NEWLINK,
+      NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST,
+      base_seq));
+
+  avd::NetlinkRequest request2(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
+  request2.AddString(0, kValue);  // Have something to work with.
+  EXPECT_THAT(request2, RequestHeaderIs(
+      kMsgLength,
+      RTM_NEWLINK,
+      NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL | NLM_F_REQUEST,
+      base_seq + 1));
 }
 
 TEST_F(NetlinkClientTest, SimpleNetlinkUpdateHeader) {
-  auto request =
-      avd::NetlinkRequest::New(RTM_SETLINK, 0);
+  avd::NetlinkRequest request(RTM_SETLINK, 0);
   constexpr char kValue[] = "random string";
-  request->AddString(0, kValue);  // Have something to work with.
+  request.AddString(0, kValue);  // Have something to work with.
 
   constexpr size_t kMsgLength =
       sizeof(nlmsghdr) + sizeof(nlattr) + RTA_ALIGN(sizeof(kValue));
+  int base_seq = request.SeqNo();
 
   EXPECT_THAT(request, RequestHeaderIs(
-      kMsgLength,  // Expected size of message.
-      RTM_SETLINK,  // Results from creane_new_iface=true in CreateRequest.
-      NLM_F_REQUEST | NLM_F_ACK,  // Ditto.
-      0u));
+      kMsgLength, RTM_SETLINK, NLM_F_REQUEST | NLM_F_ACK, base_seq));
+
+  avd::NetlinkRequest request2(RTM_SETLINK, 0);
+  request2.AddString(0, kValue);  // Have something to work with.
+  EXPECT_THAT(request2, RequestHeaderIs(
+      kMsgLength, RTM_SETLINK, NLM_F_REQUEST | NLM_F_ACK, base_seq + 1));
 }
 
 }  // namespace avd
diff --git a/common/libs/net/network_interface_manager.cpp b/common/libs/net/network_interface_manager.cpp
index d5d59b5..3d4de82e 100644
--- a/common/libs/net/network_interface_manager.cpp
+++ b/common/libs/net/network_interface_manager.cpp
@@ -29,24 +29,24 @@
 
 namespace avd {
 namespace {
-std::unique_ptr<NetlinkRequest> BuildLinkRequest(
+NetlinkRequest BuildLinkRequest(
     const NetworkInterface& interface) {
-  auto request = NetlinkRequest::New(RTM_SETLINK, 0);
-  request->AddIfInfo(interface.Index(), interface.IsOperational());
+  NetlinkRequest request(RTM_SETLINK, 0);
+  request.AddIfInfo(interface.Index(), interface.IsOperational());
   if (!interface.Name().empty()) {
-    request->AddString(IFLA_IFNAME, interface.Name());
+    request.AddString(IFLA_IFNAME, interface.Name());
   }
 
   return request;
 }
 
-std::unique_ptr<NetlinkRequest> BuildAddrRequest(
+NetlinkRequest BuildAddrRequest(
     const NetworkInterface& interface) {
-  auto request = NetlinkRequest::New(RTM_NEWADDR, 0);
-  request->AddAddrInfo(interface.Index());
-  request->AddInt32(IFA_LOCAL, inet_addr(interface.Address().c_str()));
-  request->AddInt32(IFA_ADDRESS, inet_addr(interface.Address().c_str()));
-  request->AddInt32(IFA_BROADCAST,
+  NetlinkRequest request(RTM_NEWADDR, 0);
+  request.AddAddrInfo(interface.Index());
+  request.AddInt32(IFA_LOCAL, inet_addr(interface.Address().c_str()));
+  request.AddInt32(IFA_ADDRESS, inet_addr(interface.Address().c_str()));
+  request.AddInt32(IFA_BROADCAST,
                     inet_addr(interface.BroadcastAddress().c_str()));
 
   return request;
@@ -90,14 +90,10 @@
 }
 
 bool NetworkInterfaceManager::ApplyChanges(const NetworkInterface& iface) {
-  auto request = BuildLinkRequest(iface);
-  if (!nl_client_->Send(request.get())) return false;
-
+  if (!nl_client_->Send(BuildLinkRequest(iface))) return false;
   // Terminate immediately if interface is down.
   if (!iface.IsOperational()) return true;
-
-  request = BuildAddrRequest(iface);
-  return nl_client_->Send(request.get());
+  return nl_client_->Send(BuildAddrRequest(iface));
 }
 
 }  // namespace avd