Skip to content
This repository has been archived by the owner on Sep 7, 2020. It is now read-only.

Feature/add device information tlv to topology response #705

Merged
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
#include <bpl/bpl_cfg.h>
#include <bpl/bpl_err.h>

// SPEED values
#include <linux/ethtool.h>

using namespace beerocks::net;

namespace beerocks {
Expand Down Expand Up @@ -1739,7 +1742,7 @@ bool backhaul_manager::handle_1905_1_message(ieee1905_1::CmduMessageRx &cmdu_rx,
return false;
}
case ieee1905_1::eMessageType::TOPOLOGY_QUERY_MESSAGE: {
return handle_1905_discovery_query(cmdu_rx, src_mac);
return handle_1905_topology_query(cmdu_rx, src_mac);
mariomaz marked this conversation as resolved.
Show resolved Hide resolved
//LOG(INFO) << "I got the Topology Query message!";
}
case ieee1905_1::eMessageType::HIGHER_LAYER_DATA_MESSAGE: {
Expand All @@ -1758,20 +1761,20 @@ bool backhaul_manager::handle_1905_1_message(ieee1905_1::CmduMessageRx &cmdu_rx,
}

/**
* @brief Handles 1905 Discovery Query message, currently only prints to the log
* @param cmdu_rx
* @brief Handles 1905 Topology Query message
* @param cmdu_rx Received CMDU (containing Topology Query)
* @param src_mac MAC address of the message sender
mariomaz marked this conversation as resolved.
Show resolved Hide resolved
* @return true on success
* @return false on failure
*/
bool backhaul_manager::handle_1905_discovery_query(ieee1905_1::CmduMessageRx &cmdu_rx,
const std::string &src_mac)
bool backhaul_manager::handle_1905_topology_query(ieee1905_1::CmduMessageRx &cmdu_rx,
const std::string &src_mac)
{
const auto mid = cmdu_rx.getMessageId();
LOG(DEBUG) << "Received TOPOLOGY_QUERY_MESSAGE , mid=" << std::dec << int(mid);
auto cmdu_tx_header = cmdu_tx.create(mid, ieee1905_1::eMessageType::TOPOLOGY_RESPONSE_MESSAGE);
if (!cmdu_tx_header) {
LOG(ERROR) << "Failed creating topology discovery response header! mid=" << std::hex
<< (int)mid;
LOG(ERROR) << "Failed creating topology response header! mid=" << std::hex << (int)mid;
return false;
}

Expand All @@ -1781,11 +1784,39 @@ bool backhaul_manager::handle_1905_discovery_query(ieee1905_1::CmduMessageRx &cm
<< (int)mid;
return false;
}

/**
* 1905.1 AL MAC address of the device.
*/
tlvDeviceInformation->mac() = network_utils::mac_from_string(bridge_info.mac);
mariomaz marked this conversation as resolved.
Show resolved Hide resolved

// https://github.com/prplfoundation/prplMesh/issues/300
//TODO: set number of local interfaces.
//TODO: fill info of each of the local interfaces, according to IEEE_1905 section 6.4.5
/**
* Set the number of local interfaces and fill info of each of the local interfaces, according
* to IEEE_1905 section 6.4.5
*/
uint32_t speed;
if (network_utils::linux_iface_get_speed(bridge_info.iface, speed)) {
std::shared_ptr<ieee1905_1::cLocalInterfaceInfo> localInterfaceInfo =
tlvDeviceInformation->create_local_interface_list();

ieee1905_1::eMediaType media_type = ieee1905_1::eMediaType::UNKNONWN_MEDIA;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all this can go to a static function:

static bool fill_iface_info(ieee1905_1::tlvDeviceInformation &info, const std::string iface, const sMacAddr &iface_mac);

Then call it - fill_iface_info(*info, bridge_info.iface, network_utils::mac_from_string(bridge_info.mac));

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still have to add a LocalInterfaceInfo field for each wireless interface. I'll refactor this code when I had the full picture. Promise.

if (SPEED_100 == speed) {
media_type = ieee1905_1::eMediaType::IEEE_802_3U_FAST_ETHERNET;
} else if (SPEED_1000 == speed) {
media_type = ieee1905_1::eMediaType::IEEE_802_3AB_GIGABIT_ETHERNET;
}

localInterfaceInfo->mac() = network_utils::mac_from_string(bridge_info.mac);
localInterfaceInfo->media_type() = media_type;
localInterfaceInfo->media_info_length() = 0;

tlvDeviceInformation->add_local_interface_list(localInterfaceInfo);
}

// TODO: Add a LocalInterfaceInfo field for each wireless interface.
// This is something that cannot be done at this moment because the MediaType field
// must be computed with information obtained through NL80211_CMD_GET_WIPHY command of DWPAL,
// which is currently not supported. See "Send standard NL80211 commands using DWPAL #782"

auto tlvSupportedService = cmdu_tx.addClass<wfa_map::tlvSupportedService>();
if (!tlvSupportedService) {
Expand All @@ -1805,7 +1836,7 @@ bool backhaul_manager::handle_1905_discovery_query(ieee1905_1::CmduMessageRx &cm

auto supportedServiceTuple = tlvSupportedService->supported_service_list(0);
if (!std::get<0>(supportedServiceTuple)) {
LOG(ERROR) << "Failed accessing supported_service_list";
LOG(ERROR) << "Failed accessing supported_service_list(0)";
return false;
}

Expand All @@ -1815,7 +1846,7 @@ bool backhaul_manager::handle_1905_discovery_query(ieee1905_1::CmduMessageRx &cm
if (local_master) {
auto supportedServiceTuple = tlvSupportedService->supported_service_list(1);
if (!std::get<0>(supportedServiceTuple)) {
LOG(ERROR) << "Failed accessing supported_service_list";
LOG(ERROR) << "Failed accessing supported_service_list(1)";
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ class backhaul_manager : public btl::transport_socket_thread {
// 1905 messages handlers
bool handle_1905_autoconfiguration_response(ieee1905_1::CmduMessageRx &cmdu_rx,
const std::string &src_mac);
bool handle_1905_discovery_query(ieee1905_1::CmduMessageRx &cmdu_rx,
const std::string &src_mac);
bool handle_1905_topology_query(ieee1905_1::CmduMessageRx &cmdu_rx, const std::string &src_mac);
bool handle_1905_higher_layer_data_message(ieee1905_1::CmduMessageRx &cmdu_rx,
const std::string &src_mac);
bool handle_1905_combined_infrastructure_metrics(ieee1905_1::CmduMessageRx &cmdu_rx,
Expand Down
11 changes: 11 additions & 0 deletions common/beerocks/bcl/include/bcl/network/network_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ class network_utils {
static bool linux_iface_is_up(const std::string &iface);
static bool linux_iface_is_up_and_running(const std::string &iface);

/**
* @brief Gets the speed of a network interface.
*
* @param[in] iface Name of the network interface.
* @param[out] speed On success, speed in Mbps of the network interface as defined in SPEED_*
* macros included in ethtool.h
*
* @return True if speed could be successfully obtained and false otherwise.
*/
static bool linux_iface_get_speed(const std::string &iface, uint32_t &speed);

static bool arp_send(const std::string &iface, const std::string &dst_ip,
const std::string &src_ip, sMacAddr dst_mac, sMacAddr src_mac, int count,
int arp_socket = -1);
Expand Down
84 changes: 84 additions & 0 deletions common/beerocks/bcl/source/network/network_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <linux/ethtool.h>
#include <linux/if_bridge.h>
#include <linux/if_ether.h> // ETH_P_ARP = 0x0806
#include <linux/if_packet.h> // struct sockaddr_ll (see man 7 packet)
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/sockios.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -767,6 +770,87 @@ bool network_utils::linux_iface_is_up_and_running(const std::string &iface)
return (false);
}

#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32 (SCHAR_MAX)

bool network_utils::linux_iface_get_speed(const std::string &iface, uint32_t &speed)
This conversation was marked as resolved.
Show resolved Hide resolved
{
int sock;
bool result = false;

speed = SPEED_UNKNOWN;

sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock < 0) {
LOG(ERROR) << "Can't create SOCK_DGRAM socket: " << strerror(errno);
} else {
struct ifreq ifr;
struct {
struct ethtool_link_settings req;
__u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
} ecmd;
int rc;

beerocks::string_utils::copy_string(ifr.ifr_name, iface.c_str(), sizeof(ifr.ifr_name));
ifr.ifr_data = reinterpret_cast<char *>(&ecmd);

/* Handshake with kernel to determine number of words for link
* mode bitmaps. When requested number of bitmap words is not
* the one expected by kernel, the latter returns the integer
* opposite of what it is expecting. We request length 0 below
* (aka. invalid bitmap length) to get this info.
*/
memset(&ecmd, 0, sizeof(ecmd));
ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
rc = ioctl(sock, SIOCETHTOOL, &ifr);
if (0 == rc) {
/**
* See above: we expect a strictly negative value from kernel.
*/
if ((ecmd.req.link_mode_masks_nwords >= 0) || (ETHTOOL_GLINKSETTINGS != ecmd.req.cmd)) {
LOG(ERROR) << "ETHTOOL_GLINKSETTINGS handshake failed";
} else {
/**
* Got the real ecmd.req.link_mode_masks_nwords, now send the real request
*/
ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
rc = ioctl(sock, SIOCETHTOOL, &ifr);
if (0 == rc) {
speed = ecmd.req.speed;
result = true;
}
}
}

/**
* ETHTOOL_GSET is deprecated and must be used only if ETHTOOL_GLINKSETTINGS
* didn't work
*/
if (!result) {
struct ethtool_cmd ecmd;

ifr.ifr_data = reinterpret_cast<char *>(&ecmd);

memset(&ecmd, 0, sizeof(ecmd));
ecmd.cmd = ETHTOOL_GSET;

rc = ioctl(sock, SIOCETHTOOL, &ifr);
if (0 == rc) {
speed = ethtool_cmd_speed(&ecmd);
result = true;
}
}

if (rc < 0) {
LOG(ERROR) << "ioctl failed: " << strerror(errno);
}

close(sock);
}

return result;
}

std::vector<network_utils::ip_info> network_utils::get_ip_list()
{
std::vector<network_utils::ip_info> ip_list;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
#include "tlvf/ieee_1905_1/eTlvType.h"
#include "tlvf/common/sMacAddr.h"
#include <tuple>
#include <vector>
#include "tlvf/ieee_1905_1/eMediaType.h"

namespace ieee1905_1 {

class cLocalInterfaceInfo;

class tlvDeviceInformation : public BaseClass
{
Expand All @@ -35,25 +37,13 @@ class tlvDeviceInformation : public BaseClass
explicit tlvDeviceInformation(std::shared_ptr<BaseClass> base, bool parse = false);
~tlvDeviceInformation();

typedef struct sInfo {
sMacAddr mac;
eMediaType media_type;
uint8_t media_info_length;
eMediaType media_info;
void struct_swap(){
mac.struct_swap();
}
void struct_init(){
mac.struct_init();
}
} __attribute__((packed)) sInfo;

const eTlvType& type();
const uint16_t& length();
sMacAddr& mac();
uint8_t& info_length();
std::tuple<bool, sInfo&> info(size_t idx);
bool alloc_info(size_t count = 1);
uint8_t& local_interface_list_length();
This conversation was marked as resolved.
Show resolved Hide resolved
std::tuple<bool, cLocalInterfaceInfo&> local_interface_list(size_t idx);
std::shared_ptr<cLocalInterfaceInfo> create_local_interface_list();
bool add_local_interface_list(std::shared_ptr<cLocalInterfaceInfo> ptr);
void class_swap() override;
bool finalize() override;
static size_t get_initial_size();
Expand All @@ -63,9 +53,37 @@ class tlvDeviceInformation : public BaseClass
eTlvType* m_type = nullptr;
uint16_t* m_length = nullptr;
sMacAddr* m_mac = nullptr;
uint8_t* m_info_length = nullptr;
sInfo* m_info = nullptr;
size_t m_info_idx__ = 0;
uint8_t* m_local_interface_list_length = nullptr;
This conversation was marked as resolved.
Show resolved Hide resolved
cLocalInterfaceInfo* m_local_interface_list = nullptr;
tomereli marked this conversation as resolved.
Show resolved Hide resolved
size_t m_local_interface_list_idx__ = 0;
std::vector<std::shared_ptr<cLocalInterfaceInfo>> m_local_interface_list_vector;
bool m_lock_allocation__ = false;
int m_lock_order_counter__ = 0;
};

class cLocalInterfaceInfo : public BaseClass
{
public:
cLocalInterfaceInfo(uint8_t* buff, size_t buff_len, bool parse = false);
explicit cLocalInterfaceInfo(std::shared_ptr<BaseClass> base, bool parse = false);
~cLocalInterfaceInfo();

sMacAddr& mac();
eMediaType& media_type();
uint8_t& media_info_length();
uint8_t* media_info(size_t idx = 0);
bool alloc_media_info(size_t count = 1);
void class_swap() override;
bool finalize() override;
static size_t get_initial_size();

private:
bool init();
sMacAddr* m_mac = nullptr;
eMediaType* m_media_type = nullptr;
uint8_t* m_media_info_length = nullptr;
uint8_t* m_media_info = nullptr;
size_t m_media_info_idx__ = 0;
This conversation was marked as resolved.
Show resolved Hide resolved
int m_lock_order_counter__ = 0;
};

Expand Down
Loading