Skip to content

Commit 23e6c28

Browse files
committed
Improvements based on code review discussions with Collin
- Change IpAddress from typedef to a POD type to provide some type safety - Add a third argument to Driver::receivePackets() to hold source addresses of ingress packets when the method returns - Eliminate Driver::Packet (use Homa::PacketSpec instead) - Move L4 header fields sport/dport into header prefix
1 parent a305d46 commit 23e6c28

23 files changed

+283
-190
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required (VERSION 3.11)
22

3-
project(Homa VERSION 0.1.1.0 LANGUAGES CXX)
3+
project(Homa VERSION 0.1.2.0 LANGUAGES CXX)
44

55
################################################################################
66
## Dependency Configuration ####################################################
@@ -74,6 +74,7 @@ endif()
7474
add_library(Homa
7575
src/CodeLocation.cc
7676
src/Debug.cc
77+
src/Driver.cc
7778
src/Homa.cc
7879
src/Perf.cc
7980
src/Policy.cc

include/Homa/Driver.h

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,49 @@
2222

2323
namespace Homa {
2424

25-
/// IPv4 address in host byte order.
26-
using IpAddress = uint32_t;
25+
/**
26+
* A simple wrapper struct around an IP address in binary format.
27+
*
28+
* This struct is meant to provide some type-safety when manipulating IP
29+
* addresses. In order to avoid any runtime overhead, this struct contains
30+
* nothing more than the IP address, so it is trivially copyable.
31+
*/
32+
struct IpAddress final {
33+
/// IPv4 address in host byte order.
34+
uint32_t addr;
35+
36+
/**
37+
* Unbox the IP address in binary format.
38+
*/
39+
explicit operator uint32_t()
40+
{
41+
return addr;
42+
}
43+
44+
/**
45+
* Equality function for IpAddress, for use in std::unordered_maps etc.
46+
*/
47+
bool operator==(const IpAddress& other) const
48+
{
49+
return addr == other.addr;
50+
}
51+
52+
/**
53+
* This class computes a hash of an IpAddress, so that IpAddress can be used
54+
* as keys in unordered_maps.
55+
*/
56+
struct Hasher {
57+
/// Return a "hash" of the given IpAddress.
58+
std::size_t operator()(const IpAddress& address) const
59+
{
60+
return std::hash<typeof(addr)>{}(address.addr);
61+
}
62+
};
63+
64+
static std::string toString(IpAddress address);
65+
static IpAddress fromString(const char* addressStr);
66+
};
67+
static_assert(std::is_trivially_copyable<IpAddress>());
2768

2869
/**
2970
* Represents a packet of data that can be send or is received over the network.
@@ -43,6 +84,7 @@ struct PacketSpec {
4384
/// Number of bytes in the payload.
4485
int32_t length;
4586
} __attribute__((packed));
87+
static_assert(std::is_trivial<PacketSpec>());
4688

4789
/**
4890
* Used by Homa::Transport to send and receive unreliable datagrams. Provides
@@ -52,41 +94,8 @@ struct PacketSpec {
5294
*/
5395
class Driver {
5496
public:
55-
/**
56-
* Represents a packet that can be send or is received over the network.
57-
*
58-
* The layout of this struct has two parts: the first part is essentially
59-
* a copy of PacketSpec, while the second part contains members specific
60-
* to our driver implementation.
61-
*
62-
* @sa Homa::PacketSpec
63-
*/
64-
struct Packet final {
65-
// === PacketSpec definitions ===
66-
// The order and types of the following members must match those in
67-
// PacketSpec precisely.
68-
69-
/// See Homa::PacketSpec::payload.
70-
void* payload;
71-
72-
/// See Homa::PacketSpec::length
73-
int32_t length;
74-
75-
// === Extended definitions ===
76-
// The following members are specific to the driver framework bundled
77-
// in this library. Therefore, these members must *NOT* appear in the
78-
// core components of Homa transport; they are only used in a few
79-
// places to facilitate the glue code between transport and driver.
80-
81-
/// Packet's source IpAddress. Only meaningful when this packet is an
82-
/// incoming packet.
83-
IpAddress sourceIp;
84-
} __attribute__((packed));
85-
86-
// Static checks to enforce the object layout compatibility between
87-
// Driver::Packet and PacketSpec.
88-
static_assert(offsetof(Packet, payload) == offsetof(PacketSpec, payload));
89-
static_assert(offsetof(Packet, length) == offsetof(PacketSpec, length));
97+
/// Import PacketSpec into the Driver namespace.
98+
using Packet = PacketSpec;
9099

91100
/**
92101
* Driver destructor.
@@ -164,14 +173,18 @@ class Driver {
164173
* this method.
165174
* @param[out] receivedPackets
166175
* Received packets are appended to this array in order of arrival.
176+
* @param[out] sourceAddresses
177+
* Source IP addresses of the received packets are appended to this
178+
* array in order of arrival.
167179
*
168180
* @return
169181
* Number of Packet objects being returned.
170182
*
171183
* @sa Driver::releasePackets()
172184
*/
173185
virtual uint32_t receivePackets(uint32_t maxPackets,
174-
Packet* receivedPackets[]) = 0;
186+
Packet* receivedPackets[],
187+
IpAddress sourceAddresses[]) = 0;
175188

176189
/**
177190
* Release a collection of Packet objects back to the Driver. Every

include/Homa/Drivers/DPDK/DpdkDriver.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ class DpdkDriver : public Driver {
133133

134134
/// See Driver::receivePackets()
135135
virtual uint32_t receivePackets(uint32_t maxPackets,
136-
Packet* receivedPackets[]);
136+
Packet* receivedPackets[],
137+
IpAddress sourceAddresses[]);
137138

138139
/// See Driver::releasePackets()
139140
virtual void releasePackets(Packet* packets[], uint16_t numPackets);

include/Homa/Drivers/Fake/FakeDriver.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,27 @@ struct FakePacket {
5858
/// Raw storage for this packets payload.
5959
char buf[MAX_PAYLOAD_SIZE];
6060

61+
/// Source IpAddress of the packet.
62+
IpAddress sourceIp;
63+
6164
/**
6265
* FakePacket constructor.
6366
*/
6467
explicit FakePacket()
6568
: base{.payload = buf,
66-
.length = 0,
67-
.sourceIp = 0}
69+
.length = 0}
6870
, buf()
71+
, sourceIp()
6972
{}
7073

7174
/**
7275
* Copy constructor.
7376
*/
7477
FakePacket(const FakePacket& other)
7578
: base{.payload = buf,
76-
.length = other.base.length,
77-
.sourceIp = 0}
79+
.length = other.base.length}
7880
, buf()
81+
, sourceIp()
7982
{
8083
memcpy(base.payload, other.base.payload, MAX_PAYLOAD_SIZE);
8184
}
@@ -111,7 +114,8 @@ class FakeDriver : public Driver {
111114
virtual Packet* allocPacket();
112115
virtual void sendPacket(Packet* packet, IpAddress destination, int priority);
113116
virtual uint32_t receivePackets(uint32_t maxPackets,
114-
Packet* receivedPackets[]);
117+
Packet* receivedPackets[],
118+
IpAddress sourceAddresses[]);
115119
virtual void releasePackets(Packet* packets[], uint16_t numPackets);
116120
virtual int getHighestPacketPriority();
117121
virtual uint32_t getMaxPayloadSize();
@@ -121,7 +125,7 @@ class FakeDriver : public Driver {
121125

122126
private:
123127
/// Identifier for this driver on the fake network.
124-
uint64_t localAddressId;
128+
uint32_t localAddressId;
125129

126130
/// Holds the incoming packets for this driver.
127131
FakeNIC nic;

include/Homa/Util.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@
2222
#include <string>
2323

2424
/// Cast a member of a structure out to the containing structure.
25-
#define container_of(ptr, type, member) ({ \
26-
const typeof( ((type *)0)->member ) \
27-
*__mptr = (ptr); \
28-
(type *)( (char *)__mptr - offsetof(type,member) );})
25+
template<class P, class M>
26+
P* container_of(M* ptr, const M P::*member)
27+
{
28+
return (P*)((char*) ptr - (size_t) &(reinterpret_cast<P*>(0)->*member));
29+
}
2930

3031
namespace Homa {
3132
namespace Util {
@@ -57,8 +58,6 @@ downCast(const Large& large)
5758

5859
std::string demangle(const char* name);
5960
std::string hexDump(const void* buf, uint64_t bytes);
60-
std::string ipToString(uint32_t ip);
61-
uint32_t stringToIp(const char* ip);
6261

6362
/**
6463
* This class is used to temporarily release lock in a safe fashion. Creating

src/Driver.cc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* Copyright (c) 2018-2019, Stanford University
2+
*
3+
* Permission to use, copy, modify, and/or distribute this software for any
4+
* purpose with or without fee is hereby granted, provided that the above
5+
* copyright notice and this permission notice appear in all copies.
6+
*
7+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14+
*/
15+
16+
#include <Homa/Driver.h>
17+
18+
#include "StringUtil.h"
19+
20+
namespace Homa {
21+
22+
std::string
23+
IpAddress::toString(IpAddress address)
24+
{
25+
uint32_t ip = address.addr;
26+
return StringUtil::format("%d.%d.%d.%d",
27+
(ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
28+
}
29+
30+
IpAddress
31+
IpAddress::fromString(const char* addressStr)
32+
{
33+
unsigned int b0, b1, b2, b3;
34+
sscanf(addressStr, "%u.%u.%u.%u", &b0, &b1, &b2, &b3);
35+
return IpAddress{(b0 << 24u) | (b1 << 16u) | (b2 << 8u) | b3};
36+
}
37+
38+
} // namespace Homa

src/Drivers/DPDK/DpdkDriver.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ DpdkDriver::uncork()
6666

6767
/// See Driver::receivePackets()
6868
uint32_t
69-
DpdkDriver::receivePackets(uint32_t maxPackets, Packet* receivedPackets[])
69+
DpdkDriver::receivePackets(uint32_t maxPackets, Packet* receivedPackets[],
70+
IpAddress sourceAddresses[])
7071
{
71-
return pImpl->receivePackets(maxPackets, receivedPackets);
72+
return pImpl->receivePackets(maxPackets, receivedPackets, sourceAddresses);
7273
}
7374
/// See Driver::releasePackets()
7475
void

src/Drivers/DPDK/DpdkDriverImpl.cc

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ const char* default_eal_argv[] = {"homa", NULL};
5151
* Memory location in the mbuf where the packet data should be stored.
5252
*/
5353
DpdkDriver::Impl::Packet::Packet(struct rte_mbuf* mbuf, void* data)
54-
: base {.payload = data, .length = 0, .sourceIp = 0}
54+
: base {.payload = data,
55+
.length = 0}
5556
, bufType(MBUF)
5657
, bufRef()
5758
{
@@ -65,7 +66,8 @@ DpdkDriver::Impl::Packet::Packet(struct rte_mbuf* mbuf, void* data)
6566
* Overflow buffer that holds this packet.
6667
*/
6768
DpdkDriver::Impl::Packet::Packet(OverflowBuffer* overflowBuf)
68-
: base {.payload = overflowBuf->data, .length = 0, .sourceIp = 0}
69+
: base {.payload = overflowBuf->data,
70+
.length = 0}
6971
, bufType(OVERFLOW_BUF)
7072
, bufRef()
7173
{
@@ -252,7 +254,8 @@ DpdkDriver::Impl::sendPacket(Driver::Packet* packet, IpAddress destination,
252254
vlanHdr->eth_proto = rte_cpu_to_be_16(EthPayloadType::HOMA);
253255

254256
// Store our local IP address right before the payload.
255-
*rte_pktmbuf_mtod_offset(mbuf, uint32_t*, PACKET_HDR_LEN - 4) = localIp;
257+
*rte_pktmbuf_mtod_offset(mbuf, uint32_t*, PACKET_HDR_LEN - 4) =
258+
(uint32_t)localIp;
256259

257260
// In the normal case, we pre-allocate a pakcet's mbuf with enough
258261
// storage to hold the MAX_PAYLOAD_SIZE. If the actual payload is
@@ -322,7 +325,8 @@ DpdkDriver::Impl::uncork()
322325
// See Driver::receivePackets()
323326
uint32_t
324327
DpdkDriver::Impl::receivePackets(uint32_t maxPackets,
325-
Driver::Packet* receivedPackets[])
328+
Driver::Packet* receivedPackets[],
329+
IpAddress sourceAddresses[])
326330
{
327331
uint32_t numPacketsReceived = 0;
328332

@@ -398,9 +402,10 @@ DpdkDriver::Impl::receivePackets(uint32_t maxPackets,
398402
packet = packetPool.construct(m, payload);
399403
}
400404
packet->base.length = length;
401-
packet->base.sourceIp = srcIp;
402405

403-
receivedPackets[numPacketsReceived++] = &packet->base;
406+
receivedPackets[numPacketsReceived] = &packet->base;
407+
sourceAddresses[numPacketsReceived] = {srcIp};
408+
++numPacketsReceived;
404409
}
405410

406411
return numPacketsReceived;
@@ -504,7 +509,7 @@ DpdkDriver::Impl::_init()
504509
int cols = sscanf(line.c_str(), "%s 0x%x 0x%x %99s %99s %99s\n",
505510
ip, &type, &flags, hwa, mask, dev);
506511
if (cols != 6) continue;
507-
arpTable.emplace(Homa::Util::stringToIp(ip), hwa);
512+
arpTable.emplace(IpAddress::fromString(ip), hwa);
508513
}
509514

510515
// Use ioctl to obtain the IP and MAC addresses of the network interface.
@@ -528,7 +533,7 @@ DpdkDriver::Impl::_init()
528533
throw DriverInitFailure(HERE_STR,
529534
StringUtil::format("Failed to obtain IP address: %s", error));
530535
}
531-
localIp = be32toh(((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr);
536+
localIp = {be32toh(((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr)};
532537

533538
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
534539
char* error = strerror(errno);
@@ -550,7 +555,7 @@ DpdkDriver::Impl::_init()
550555
}
551556
}
552557
NOTICE("Using interface %s, ip %s, mac %s, port %u",
553-
ifname.c_str(), Homa::Util::ipToString(localIp).c_str(),
558+
ifname.c_str(), IpAddress::toString(localIp).c_str(),
554559
localMac.toString().c_str(), port);
555560

556561
std::string poolName = StringUtil::format("homa_mbuf_pool_%u", port);

src/Drivers/DPDK/DpdkDriverImpl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ class DpdkDriver::Impl {
145145
void cork();
146146
void uncork();
147147
uint32_t receivePackets(uint32_t maxPackets,
148-
Driver::Packet* receivedPackets[]);
148+
Driver::Packet* receivedPackets[],
149+
IpAddress sourceAddresses[]);
149150
void releasePackets(Driver::Packet* packets[], uint16_t numPackets);
150151
int getHighestPacketPriority();
151152
uint32_t getMaxPayloadSize();
@@ -171,7 +172,7 @@ class DpdkDriver::Impl {
171172
uint16_t port;
172173

173174
/// Address resolution table that translates IP addresses to MAC addresses.
174-
std::unordered_map<IpAddress, MacAddress> arpTable;
175+
std::unordered_map<IpAddress, MacAddress, IpAddress::Hasher> arpTable;
175176

176177
/// Stores the IpAddress of the driver.
177178
IpAddress localIp;

0 commit comments

Comments
 (0)