Merge pull request #13902 from artokin/set_mac_address

[feature-wisun] Network interface MAC address set/get
pull/14054/head feature-wisun-1.4.0
Martin Kojtal 2020-12-14 13:52:44 +00:00 committed by GitHub
commit 84d991342a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 174 additions and 10 deletions

View File

@ -155,6 +155,11 @@ char *EmacTestNetworkStack::Interface::get_mac_address(char *buf, nsapi_size_t b
return NULL; return NULL;
} }
nsapi_error_t EmacTestNetworkStack::Interface::set_mac_address(uint8_t *buf, nsapi_size_t buflen)
{
return NSAPI_STATUS_ERROR_UNSUPPORTED;
}
nsapi_error_t EmacTestNetworkStack::Interface::get_ip_address(SocketAddress *address) nsapi_error_t EmacTestNetworkStack::Interface::get_ip_address(SocketAddress *address)
{ {
return NSAPI_ERROR_OK; return NSAPI_ERROR_OK;

View File

@ -86,6 +86,17 @@ public:
*/ */
virtual char *get_mac_address(char *buf, nsapi_size_t buflen); virtual char *get_mac_address(char *buf, nsapi_size_t buflen);
/** Set MAC address on the network interface
*
* @param mac_addr Buffer containing the MAC address in hexadecimal format.
* @param addr_len Length of provided buffer in bytes (6 or 8)
* @retval NSAPI_ERROR_OK on success
* @retval NSAPI_ERROR_UNSUPPORTED if this feature is not supported
* @retval NSAPI_ERROR_PARAMETER if address is not valid
* @retval NSAPI_ERROR_BUSY if address can't be set.
*/
virtual nsapi_error_t set_mac_address(uint8_t *mac_addr, nsapi_size_t addr_len);
/** Copies IP address of the network interface to user supplied buffer /** Copies IP address of the network interface to user supplied buffer
* *
* @param buf buffer to which IP address will be copied as "W:X:Y:Z" * @param buf buffer to which IP address will be copied as "W:X:Y:Z"

View File

@ -75,6 +75,12 @@ TEST_F(TestNetworkInterface, get_mac_address)
EXPECT_EQ(iface->get_mac_address(), n); EXPECT_EQ(iface->get_mac_address(), n);
} }
TEST_F(TestNetworkInterface, set_mac_address)
{
uint8_t mac_buf[8];
EXPECT_EQ(iface->set_mac_address(mac_buf, 8), NSAPI_ERROR_UNSUPPORTED);
}
TEST_F(TestNetworkInterface, get_ip_address) TEST_F(TestNetworkInterface, get_ip_address)
{ {
SocketAddress addr; SocketAddress addr;

View File

@ -26,6 +26,11 @@ const char *NetworkInterface::get_mac_address()
return 0; return 0;
} }
nsapi_error_t NetworkInterface::set_mac_address(uint8_t *mac_addr, nsapi_size_t addr_len)
{
return NSAPI_ERROR_UNSUPPORTED;
}
nsapi_error_t NetworkInterface::get_ip_address(SocketAddress *) nsapi_error_t NetworkInterface::get_ip_address(SocketAddress *)
{ {
return NSAPI_ERROR_UNSUPPORTED; return NSAPI_ERROR_UNSUPPORTED;

View File

@ -29,6 +29,7 @@ public:
MBED_DEPRECATED_SINCE("mbed-os-5.15", "String-based APIs are deprecated") MBED_DEPRECATED_SINCE("mbed-os-5.15", "String-based APIs are deprecated")
virtual char *get_ip_address(char *buf, nsapi_size_t buflen); virtual char *get_ip_address(char *buf, nsapi_size_t buflen);
virtual char *get_mac_address(char *buf, nsapi_size_t buflen); virtual char *get_mac_address(char *buf, nsapi_size_t buflen);
virtual nsapi_error_t set_mac_address(uint8_t *buf, nsapi_size_t buflen);
virtual nsapi_error_t get_netmask(SocketAddress *address); virtual nsapi_error_t get_netmask(SocketAddress *address);
MBED_DEPRECATED_SINCE("mbed-os-5.15", "String-based APIs are deprecated") MBED_DEPRECATED_SINCE("mbed-os-5.15", "String-based APIs are deprecated")
virtual char *get_netmask(char *buf, nsapi_size_t buflen); virtual char *get_netmask(char *buf, nsapi_size_t buflen);
@ -37,14 +38,7 @@ public:
virtual char *get_gateway(char *buf, nsapi_size_t buflen); virtual char *get_gateway(char *buf, nsapi_size_t buflen);
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb); virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
virtual nsapi_connection_status_t get_connection_status() const; virtual nsapi_connection_status_t get_connection_status() const;
virtual void get_mac_address(uint8_t *buf) const;
void get_mac_address(uint8_t *buf) const
{
NanostackMACPhy *phy = interface_phy.nanostack_mac_phy();
if (phy) {
phy->get_mac_address(buf);
}
}
/** /**
* \brief Callback from C-layer * \brief Callback from C-layer
@ -118,6 +112,9 @@ public:
*/ */
virtual const char *get_mac_address(); virtual const char *get_mac_address();
/** @copydoc NetworkInterface::set_mac_address */
virtual nsapi_error_t set_mac_address(uint8_t *mac_addr, nsapi_size_t addr_len);
/** Register callback for status reporting /** Register callback for status reporting
* *
* The specified status callback function will be called on status changes * The specified status callback function will be called on status changes

View File

@ -28,6 +28,8 @@ public:
nsapi_ip_stack_t stack = DEFAULT_STACK, nsapi_ip_stack_t stack = DEFAULT_STACK,
bool blocking = true); bool blocking = true);
virtual nsapi_error_t bringdown(); virtual nsapi_error_t bringdown();
virtual void get_mac_address(uint8_t *buf);
virtual char *get_mac_address(char *buf, nsapi_size_t buflen);
char *get_interface_name(char *buf); char *get_interface_name(char *buf);
private: private:

View File

@ -61,6 +61,27 @@ char *Nanostack::Interface::get_mac_address(char *buf, nsapi_size_t buflen)
} }
} }
nsapi_error_t Nanostack::Interface::set_mac_address(uint8_t *buf, nsapi_size_t buflen)
{
if (buflen != 8) {
/* Provided MAC is too short */
return NSAPI_ERROR_PARAMETER;
}
if (_device_id >= 0) {
/* device is already registered, can't set MAC address anymore */
return NSAPI_ERROR_BUSY;
}
NanostackMACPhy *phy = interface_phy.nanostack_mac_phy();
if (phy) {
phy->set_mac_address(buf);
return NSAPI_ERROR_OK;
}
return NSAPI_ERROR_UNSUPPORTED;
}
nsapi_error_t Nanostack::Interface::get_netmask(SocketAddress *address) nsapi_error_t Nanostack::Interface::get_netmask(SocketAddress *address)
{ {
return NSAPI_ERROR_UNSUPPORTED; return NSAPI_ERROR_UNSUPPORTED;
@ -86,6 +107,14 @@ nsapi_connection_status_t Nanostack::Interface::get_connection_status() const
return _connect_status; return _connect_status;
} }
void Nanostack::Interface::get_mac_address(uint8_t *buf) const
{
NanostackMACPhy *phy = interface_phy.nanostack_mac_phy();
if (phy) {
phy->get_mac_address(buf);
}
}
void Nanostack::Interface::attach( void Nanostack::Interface::attach(
mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
{ {
@ -237,6 +266,11 @@ const char *InterfaceNanostack::get_mac_address()
return NULL; return NULL;
} }
nsapi_error_t InterfaceNanostack::set_mac_address(uint8_t *mac_addr, nsapi_size_t addr_len)
{
return _interface->set_mac_address(mac_addr, addr_len);
}
nsapi_connection_status_t InterfaceNanostack::get_connection_status() const nsapi_connection_status_t InterfaceNanostack::get_connection_status() const
{ {
if (_interface) { if (_interface) {

View File

@ -209,7 +209,14 @@ nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, Nan
*interface_out = interface; *interface_out = interface;
return NSAPI_ERROR_OK; return NSAPI_ERROR_OK;
}
nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, const uint8_t *mac_addr)
{
Nanostack::EthernetInterface *interface;
nsapi_error_t err = add_ethernet_interface(emac, default_if, &interface, mac_addr);
*interface_out = interface;
return err;
} }
nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out) nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)

View File

@ -129,3 +129,26 @@ char *Nanostack::EthernetInterface::get_interface_name(char *buf)
sprintf(buf, "ETH%d", interface_id); sprintf(buf, "ETH%d", interface_id);
return buf; return buf;
}; };
void Nanostack::EthernetInterface::get_mac_address(uint8_t *buf)
{
if (!buf) {
return;
}
get_phy().get_mac_address(buf);
}
char *Nanostack::EthernetInterface::get_mac_address(char *buf, nsapi_size_t buflen)
{
uint8_t mac_buf[NSAPI_MAC_BYTES] = {0};
if (!buf || buflen < NSAPI_MAC_SIZE) {
return NULL;
}
get_phy().get_mac_address(mac_buf);
snprintf(buf, buflen, "%02x:%02x:%02x:%02x:%02x:%02x", mac_buf[0], mac_buf[1], mac_buf[2], mac_buf[3], mac_buf[4], mac_buf[5]);
return buf;
}

View File

@ -41,6 +41,7 @@ public:
/* Implement OnboardNetworkStack method */ /* Implement OnboardNetworkStack method */
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out); virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out);
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, const uint8_t *mac_addr);
/* Local variant with stronger typing and manual address specification */ /* Local variant with stronger typing and manual address specification */
nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Nanostack::EthernetInterface **interface_out, const uint8_t *mac_addr = NULL); nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Nanostack::EthernetInterface **interface_out, const uint8_t *mac_addr = NULL);

View File

@ -15,9 +15,12 @@
*/ */
#include "EMACInterface.h" #include "EMACInterface.h"
#include "mbed-trace/mbed_trace.h"
using namespace mbed; using namespace mbed;
#define TRACE_GROUP "EMACi"
/* Interface implementation */ /* Interface implementation */
EMACInterface::EMACInterface(EMAC &emac, OnboardNetworkStack &stack) : EMACInterface::EMACInterface(EMAC &emac, OnboardNetworkStack &stack) :
_emac(emac), _emac(emac),
@ -25,6 +28,7 @@ EMACInterface::EMACInterface(EMAC &emac, OnboardNetworkStack &stack) :
_interface(NULL), _interface(NULL),
_dhcp(true), _dhcp(true),
_blocking(true), _blocking(true),
_hw_mac_addr_set(false),
_ip_address(), _ip_address(),
_netmask(), _netmask(),
_gateway() _gateway()
@ -68,7 +72,19 @@ nsapi_error_t EMACInterface::set_dhcp(bool dhcp)
nsapi_error_t EMACInterface::connect() nsapi_error_t EMACInterface::connect()
{ {
if (!_interface) { if (!_interface) {
nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface); nsapi_error_t err = NSAPI_ERROR_UNSUPPORTED;
if (_hw_mac_addr_set) {
err = _stack.add_ethernet_interface(_emac, true, &_interface, _hw_mac_addr);
if (err == NSAPI_ERROR_UNSUPPORTED) {
tr_error("Failed to set user MAC address");
}
}
if (err == NSAPI_ERROR_UNSUPPORTED) {
err = _stack.add_ethernet_interface(_emac, true, &_interface);
}
if (err != NSAPI_ERROR_OK) { if (err != NSAPI_ERROR_OK) {
_interface = NULL; _interface = NULL;
return err; return err;
@ -100,6 +116,23 @@ const char *EMACInterface::get_mac_address()
return nullptr; return nullptr;
} }
nsapi_error_t EMACInterface::set_mac_address(uint8_t *mac_addr, nsapi_size_t addr_len)
{
if (!mac_addr || addr_len != NSAPI_MAC_BYTES) {
return NSAPI_ERROR_PARAMETER;
}
if (_interface) {
// can't set MAC address once initialized
return NSAPI_ERROR_BUSY;
}
memcpy(_hw_mac_addr, mac_addr, addr_len);
_hw_mac_addr_set = true;
return NSAPI_ERROR_OK;
}
nsapi_error_t EMACInterface::get_ip_address(SocketAddress *address) nsapi_error_t EMACInterface::get_ip_address(SocketAddress *address)
{ {
if (_interface && _interface->get_ip_address(address) == NSAPI_ERROR_OK) { if (_interface && _interface->get_ip_address(address) == NSAPI_ERROR_OK) {

View File

@ -99,6 +99,9 @@ public:
*/ */
virtual const char *get_mac_address(); virtual const char *get_mac_address();
/** @copydoc NetworkInterface::set_mac_address */
virtual nsapi_error_t set_mac_address(uint8_t *mac_addr, nsapi_size_t addr_len);
/** Get the local IP address /** Get the local IP address
* *
* @return Null-terminated representation of the local IP address * @return Null-terminated representation of the local IP address
@ -196,10 +199,12 @@ protected:
OnboardNetworkStack::Interface *_interface; OnboardNetworkStack::Interface *_interface;
bool _dhcp; bool _dhcp;
bool _blocking; bool _blocking;
bool _hw_mac_addr_set;
char _mac_address[NSAPI_MAC_SIZE]; char _mac_address[NSAPI_MAC_SIZE];
char _ip_address[NSAPI_IPv6_SIZE]; char _ip_address[NSAPI_IPv6_SIZE];
char _netmask[NSAPI_IPv4_SIZE]; char _netmask[NSAPI_IPv4_SIZE];
char _gateway[NSAPI_IPv4_SIZE]; char _gateway[NSAPI_IPv4_SIZE];
uint8_t _hw_mac_addr[NSAPI_MAC_BYTES];
mbed::Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb; mbed::Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
}; };

View File

@ -32,6 +32,11 @@ const char *NetworkInterface::get_mac_address()
return 0; return 0;
} }
nsapi_error_t NetworkInterface::set_mac_address(uint8_t *mac_addr, nsapi_size_t addr_len)
{
return NSAPI_ERROR_UNSUPPORTED;
}
nsapi_error_t NetworkInterface::get_ip_address(SocketAddress *) nsapi_error_t NetworkInterface::get_ip_address(SocketAddress *)
{ {
return NSAPI_ERROR_UNSUPPORTED; return NSAPI_ERROR_UNSUPPORTED;

View File

@ -100,6 +100,31 @@ public:
*/ */
virtual const char *get_mac_address(); virtual const char *get_mac_address();
/** Set the MAC address to the interface.
*
* Set the provided MAC address on the network interface. The address must
* be unique globally. The address must be set before calling the interface
* connect() method.
*
* Not all interfaces are supporting MAC address set and an error is not returned
* for this method call. Verify the changed MAC address by checking packet
* captures from the used network interface.
*
* 6-byte EUI-48 MAC addresses are used for Ethernet while Mesh interface is
* using 8-byte EUI-64 address.
*
* More information about obtaining MAC address can be found from:
* https://standards.ieee.org/products-services/regauth/index.html
*
* @param mac_addr Buffer containing the MAC address in hexadecimal format.
* @param addr_len Length of provided buffer in bytes (6 or 8)
* @retval NSAPI_ERROR_OK on success
* @retval NSAPI_ERROR_UNSUPPORTED if this feature is not supported
* @retval NSAPI_ERROR_PARAMETER if address is not valid
* @retval NSAPI_ERROR_BUSY if address can't be set.
*/
virtual nsapi_error_t set_mac_address(uint8_t *mac_addr, nsapi_size_t addr_len);
/** Get the local IP address /** Get the local IP address
* *
* @param address SocketAddress representation of the local IP address * @param address SocketAddress representation of the local IP address

View File

@ -159,6 +159,11 @@ public:
*/ */
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out) = 0; virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out) = 0;
virtual nsapi_error_t add_ethernet_interface(EMAC &emac, bool default_if, Interface **interface_out, const uint8_t *mac_addr)
{
return NSAPI_ERROR_UNSUPPORTED;
}
virtual nsapi_error_t add_l3ip_interface(L3IP &l3ip, bool default_if, Interface **interface_out) virtual nsapi_error_t add_l3ip_interface(L3IP &l3ip, bool default_if, Interface **interface_out)
{ {
return NSAPI_ERROR_OK; return NSAPI_ERROR_OK;