Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lpf IPoIB support #134

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions doc/sphinx/arm/dhcp4-srv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7921,9 +7921,11 @@ are clearly marked as such.
headers (including data link layer, IP, and UDP headers) are created
and parsed by Kea, rather than by the system kernel. Currently, Kea
can only parse the data-link layer headers with a format adhering to
the IEEE 802.3 standard, and assumes this data-link-layer header
the IEEE 802.3 (Ethernet) standard, and assumes this data-link-layer header
format for all interfaces. Thus, Kea does not work on interfaces
which use different data-link-layer header formats (e.g. Infiniband).
which use different data-link-layer header formats, with the exception of
LPF being able to handle InfiniBand framing, thus enabling Kea to serve
these kind of interfaces on Linux.

.. _dhcp4-srv-examples:

Expand Down
4 changes: 2 additions & 2 deletions src/lib/dhcp/dhcp4.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ enum HType {
/// arp-parameters/arp-parameters.xhtml suggest that
/// Ethernet (1) should be used in DOCSIS environment.
HTYPE_IEEE802 = 6, ///< IEEE 802.2 Token Ring
HTYPE_FDDI = 8 ///< FDDI
/// TODO Add infiniband here
HTYPE_FDDI = 8, ///< FDDI
HTYPE_INFINIBAND = 32 ///< InfiniBand
};

/* DHCP Option codes: */
Expand Down
3 changes: 3 additions & 0 deletions src/lib/dhcp/hwaddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ struct HWAddr {
/// @brief Size of an ethernet hardware address.
static const size_t ETHERNET_HWADDR_LEN = 6;

/// @brief Size of an infiniband hardware address.
static const size_t INFINIBAND_HWADDR_LEN = 20;

/// @brief Maximum size of a hardware address.
static const size_t MAX_HWADDR_LEN = 20;

Expand Down
33 changes: 31 additions & 2 deletions src/lib/dhcp/iface_mgr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ IfaceMgr::instancePtr() {
}

Iface::Iface(const std::string& name, unsigned int ifindex)
: name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
: name_(name), ifindex_(ifindex), mac_len_(0), bcast_mac_len_(0), hardware_type_(0),
flag_loopback_(false), flag_up_(false), flag_running_(false),
flag_multicast_(false), flag_broadcast_(false), flags_(0),
inactive4_(false), inactive6_(false) {
Expand Down Expand Up @@ -142,6 +142,21 @@ Iface::getPlainMac() const {
return (tmp.str());
}

std::string
Iface::getPlainBcastMac() const {
ostringstream tmp;
tmp.fill('0');
tmp << hex;
for (int i = 0; i < bcast_mac_len_; i++) {
tmp.width(2);
tmp << static_cast<int>(bcast_mac_[i]);
if (i < bcast_mac_len_-1) {
tmp << ":";
}
}
return (tmp.str());
}

void Iface::setMac(const uint8_t* mac, size_t len) {
if (len > MAX_MAC_LEN) {
isc_throw(OutOfRange, "Interface " << getFullName()
Expand All @@ -155,6 +170,19 @@ void Iface::setMac(const uint8_t* mac, size_t len) {
}
}

void Iface::setBcastMac(const uint8_t* mac, size_t len) {
if (len > MAX_MAC_LEN) {
isc_throw(OutOfRange, "Interface " << getFullName()
<< " was detected to have link address of length "
<< len << ", but maximum supported length is "
<< MAX_MAC_LEN);
}
bcast_mac_len_ = len;
if (len > 0) {
memcpy(bcast_mac_, mac, len);
}
}

bool Iface::delAddress(const isc::asiolink::IOAddress& addr) {
for (AddressCollection::iterator a = addrs_.begin(); a != addrs_.end(); ++a) {
if (a->get() == addr) {
Expand Down Expand Up @@ -791,7 +819,8 @@ IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {

out << "Detected interface " << iface->getFullName()
<< ", hwtype=" << iface->getHWType()
<< ", mac=" << iface->getPlainMac();
<< ", mac=" << iface->getPlainMac()
<< ", bcast=" << iface->getPlainBcastMac();
out << ", flags=" << hex << iface->flags_ << dec << "("
<< (iface->flag_loopback_?"LOOPBACK ":"")
<< (iface->flag_up_?"UP ":"")
Expand Down
28 changes: 28 additions & 0 deletions src/lib/dhcp/iface_mgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,28 @@ class Iface : public boost::noncopyable {
/// that returned it.
const uint8_t* getMac() const { return mac_; }

/// @brief Returns broadcast MAC address a plain text.
///
/// @return MAC address as a plain text (string)
std::string getPlainBcastMac() const;

/// @brief Sets broadcast MAC address of the interface.
///
/// @param mac pointer to bcast MAC address buffer
/// @param macLen length of bcast mac address
void setBcastMac(const uint8_t* bcastMac, size_t bcastMacLen);

/// @brief Returns broadcast MAC length.
///
/// @return length of bcast MAC address
size_t getBcastMacLen() const { return bcast_mac_len_; }

/// @brief Returns pointer to broadcast MAC address.
///
/// Note: Returned pointer is only valid as long as the interface object
/// that returned it.
const uint8_t* getBcastMac() const { return bcast_mac_; }

/// @brief Sets flag_*_ fields based on bitmask value returned by OS
///
/// @note Implementation of this method is OS-dependent as bits have
Expand Down Expand Up @@ -430,6 +452,12 @@ class Iface : public boost::noncopyable {
/// Length of link-layer address (usually 6).
size_t mac_len_;

/// Link-layer braodcast address.
uint8_t bcast_mac_[MAX_MAC_LEN];

/// Length of link-layer broadcast address (usually 6).
size_t bcast_mac_len_;

/// Hardware type.
uint16_t hardware_type_;

Expand Down
28 changes: 28 additions & 0 deletions src/lib/dhcp/iface_mgr_bsd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ using namespace isc;
using namespace isc::asiolink;
using namespace isc::dhcp;

namespace {

static const uint8_t default_ib_bcast_addr[20] = {
0x00, 0xff, 0xff, 0xff,
0xff, 0x12, 0x40, 0x1b,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff
};

static const uint8_t default_ether_bcast_addr[6] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

}

namespace isc {
namespace dhcp {

Expand Down Expand Up @@ -92,6 +108,18 @@ IfaceMgr::detectIfaces(bool update_only) {

iface_iter->second->setHWType(ldata->sdl_type);
iface_iter->second->setMac(ptr, ldata->sdl_alen);

//TODO: I don't have BSD, this needs tested
if (ifptr->ifa_flags & IFF_BROADCAST) {
ldata = reinterpret_cast<struct sockaddr_dl *>(ifptr->ifa_broadaddr);
ptr = reinterpret_cast<uint8_t *>(LLADDR(ldata));

iface_iter->second->setBcastMac(ptr, ldata->sdl_alen);
} else if (interface_info->ifi_type == HTYPE_INFINIBAND) {
iface_iter->second->setBcastMac(default_ib_bcast_addr, sizeof(default_ib_bcast_addr));
} else if (interface_info->ifi_type == HTYPE_ETHER) {
iface_iter->second->setBcastMac(default_ether_bcast_addr, sizeof(default_ether_bcast_addr));
}
} else if (ifptr->ifa_addr->sa_family == AF_INET6) {
// IPv6 Addr
struct sockaddr_in6 * adata =
Expand Down
22 changes: 22 additions & 0 deletions src/lib/dhcp/iface_mgr_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,18 @@ void Netlink::release_list(NetlinkMessages& messages) {
messages.clear();
}

static const uint8_t default_ib_bcast_addr[20] = {
0x00, 0xff, 0xff, 0xff,
0xff, 0x12, 0x40, 0x1b,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff
};

static const uint8_t default_ether_bcast_addr[6] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

} // end of anonymous namespace

namespace isc {
Expand Down Expand Up @@ -504,6 +516,16 @@ void IfaceMgr::detectIfaces(bool update_only) {
// try to dereference it in this manner
}

// Does interface have an L2 broadcast address?
if ((interface_info->ifi_flags & IFF_BROADCAST) && attribs_table[IFLA_BROADCAST]) {
iface->setBcastMac(static_cast<const uint8_t*>(RTA_DATA(attribs_table[IFLA_BROADCAST])),
RTA_PAYLOAD(attribs_table[IFLA_BROADCAST]));
} else if (interface_info->ifi_type == HTYPE_INFINIBAND) {
iface->setBcastMac(default_ib_bcast_addr, sizeof(default_ib_bcast_addr));
} else if (interface_info->ifi_type == HTYPE_ETHER) {
iface->setBcastMac(default_ether_bcast_addr, sizeof(default_ether_bcast_addr));
}

nl.ipaddrs_get(*iface, addr_info);

// addInterface can now throw so protect against memory leaks.
Expand Down
28 changes: 28 additions & 0 deletions src/lib/dhcp/iface_mgr_sun.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ using namespace isc;
using namespace isc::asiolink;
using namespace isc::dhcp;

namespace {

static const uint8_t default_ib_bcast_addr[20] = {
0x00, 0xff, 0xff, 0xff,
0xff, 0x12, 0x40, 0x1b,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff
};

static const uint8_t default_ether_bcast_addr[6] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

}

namespace isc {
namespace dhcp {

Expand Down Expand Up @@ -92,6 +108,18 @@ IfaceMgr::detectIfaces(bool update_only) {

iface_iter->second->setHWType(ldata->sdl_type);
iface_iter->second->setMac(ptr, ldata->sdl_alen);

//TODO: I don't have SUN, this needs tested
if (ifptr->ifa_flags & IFF_BROADCAST) {
ldata = reinterpret_cast<struct sockaddr_dl *>(ifptr->ifa_broadaddr);
ptr = reinterpret_cast<uint8_t *>(LLADDR(ldata));

iface_iter->second->setBcastMac(ptr, ldata->sdl_alen);
} else if (ldata->sdl_type == HTYPE_INFINIBAND) {
iface_iter->second->setBcastMac(default_ib_bcast_addr, sizeof(default_ib_bcast_addr));
} else if (ldata->sdl_type == HTYPE_ETHER) {
iface_iter->second->setBcastMac(default_ether_bcast_addr, sizeof(default_ether_bcast_addr));
}
} else if (ifptr->ifa_addr->sa_family == AF_INET6) {
// IPv6 Addr
struct sockaddr_in6 * adata =
Expand Down
19 changes: 11 additions & 8 deletions src/lib/dhcp/pkt4.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ Pkt4::pack() {

try {
size_t hw_len = hwaddr_->hwaddr_.size();
size_t hw_offset = 0;

if (hwaddr_->htype_ == HTYPE_INFINIBAND && hw_len == HWAddr::INFINIBAND_HWADDR_LEN) {
// According to RFC4390, hlen MUST be zero and chaddr zeroed out.
// However, at least dhclient can't handle that and fails.
// Instead, return the last 8 bytes, which contain the actual unique hw part.
hw_len = 8;
hw_offset = HWAddr::INFINIBAND_HWADDR_LEN - 8;
}

buffer_out_.writeUint8(op_);
buffer_out_.writeUint8(hwaddr_->htype_);
Expand All @@ -101,7 +110,7 @@ Pkt4::pack() {
if ((hw_len > 0) && (hw_len <= MAX_CHADDR_LEN)) {
// write up to 16 bytes of the hardware address (CHADDR field is 16
// bytes long in DHCPv4 message).
buffer_out_.writeData(&hwaddr_->hwaddr_[0],
buffer_out_.writeData(&hwaddr_->hwaddr_[hw_offset],
(hw_len < MAX_CHADDR_LEN ?
hw_len : MAX_CHADDR_LEN) );
hw_len = MAX_CHADDR_LEN - hw_len;
Expand Down Expand Up @@ -481,13 +490,7 @@ void
Pkt4::setHWAddrMember(const uint8_t htype, const uint8_t hlen,
const std::vector<uint8_t>& mac_addr,
HWAddrPtr& hw_addr) {
/// @todo Rewrite this once support for client-identifier option
/// is implemented (ticket 1228?)
if (hlen > MAX_CHADDR_LEN) {
isc_throw(OutOfRange, "Hardware address (len=" << static_cast<uint32_t>(hlen)
<< ") too long. Max " << MAX_CHADDR_LEN << " supported.");

} else if (mac_addr.empty() && (hlen > 0) ) {
if (mac_addr.empty() && (hlen > 0) ) {
isc_throw(OutOfRange, "Invalid HW Address specified");
}

Expand Down
Loading