blob: a3fc4beec14c050565b8341c9136741c09c70205 [file] [log] [blame]
/*
* Copyright (c) 2018 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <net/net_if.h>
#include <net/ethernet.h>
#include <net/ethernet_mgmt.h>
#include <ztest.h>
static const u8_t mac_addr_init[6] = { 0x01, 0x02, 0x03,
0x04, 0x05, 0x06 };
static const u8_t mac_addr_change[6] = { 0x01, 0x02, 0x03,
0x04, 0x05, 0x07 };
struct eth_fake_context {
struct net_if *iface;
u8_t mac_address[6];
bool auto_negotiation;
bool full_duplex;
bool link_10bt;
bool link_100bt;
};
static struct eth_fake_context eth_fake_data;
static void eth_fake_iface_init(struct net_if *iface)
{
struct device *dev = net_if_get_device(iface);
struct eth_fake_context *ctx = dev->driver_data;
ctx->iface = iface;
net_if_set_link_addr(iface, ctx->mac_address,
sizeof(ctx->mac_address),
NET_LINK_ETHERNET);
ethernet_init(iface);
}
static int eth_fake_send(struct net_if *iface,
struct net_pkt *pkt)
{
ARG_UNUSED(iface);
net_pkt_unref(pkt);
return 0;
}
static enum ethernet_hw_caps eth_fake_get_capabilities(struct device *dev)
{
return ETHERNET_AUTO_NEGOTIATION_SET | ETHERNET_LINK_10BASE_T |
ETHERNET_LINK_100BASE_T | ETHERNET_DUPLEX_SET;
}
static int eth_fake_set_config(struct device *dev,
enum ethernet_config_type type,
const struct ethernet_config *config)
{
struct eth_fake_context *ctx = dev->driver_data;
switch (type) {
case ETHERNET_CONFIG_TYPE_AUTO_NEG:
if (config->auto_negotiation == ctx->auto_negotiation) {
return -EALREADY;
}
ctx->auto_negotiation = config->auto_negotiation;
break;
case ETHERNET_CONFIG_TYPE_LINK:
if ((config->l.link_10bt && ctx->link_10bt) ||
(config->l.link_100bt && ctx->link_100bt)) {
return -EALREADY;
}
if (config->l.link_10bt) {
ctx->link_10bt = true;
ctx->link_100bt = false;
} else {
ctx->link_10bt = false;
ctx->link_100bt = true;
}
break;
case ETHERNET_CONFIG_TYPE_DUPLEX:
if (config->full_duplex == ctx->full_duplex) {
return -EALREADY;
}
ctx->full_duplex = config->full_duplex;
break;
case ETHERNET_CONFIG_TYPE_MAC_ADDRESS:
memcpy(ctx->mac_address, config->mac_address.addr, 6);
net_if_set_link_addr(ctx->iface, ctx->mac_address,
sizeof(ctx->mac_address),
NET_LINK_ETHERNET);
break;
}
return 0;
}
static struct ethernet_api eth_fake_api_funcs = {
.iface_api.init = eth_fake_iface_init,
.iface_api.send = eth_fake_send,
.get_capabilities = eth_fake_get_capabilities,
.set_config = eth_fake_set_config,
};
static int eth_fake_init(struct device *dev)
{
struct eth_fake_context *ctx = dev->driver_data;
ctx->auto_negotiation = true;
ctx->full_duplex = true;
ctx->link_10bt = true;
ctx->link_100bt = false;
memcpy(ctx->mac_address, mac_addr_init, 6);
return 0;
}
ETH_NET_DEVICE_INIT(eth_fake, "eth_fake", eth_fake_init, &eth_fake_data,
NULL, CONFIG_ETH_INIT_PRIORITY, &eth_fake_api_funcs, 1500);
static void test_change_mac_when_up(void)
{
struct net_if *iface = net_if_get_default();
struct ethernet_req_params params;
int ret;
memcpy(params.mac_address.addr, mac_addr_change, 6);
ret = net_mgmt(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS, iface,
&params, sizeof(struct ethernet_req_params));
zassert_not_equal(ret, 0,
"mac address change should not be possible\n");
}
static void test_change_mac_when_down(void)
{
struct net_if *iface = net_if_get_default();
struct ethernet_req_params params;
int ret;
memcpy(params.mac_address.addr, mac_addr_change, 6);
net_if_down(iface);
ret = net_mgmt(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS, iface,
&params, sizeof(struct ethernet_req_params));
zassert_equal(ret, 0, "unable to change mac address\n");
ret = memcmp(net_if_get_link_addr(iface)->addr, mac_addr_change,
sizeof(mac_addr_change));
zassert_equal(ret, 0, "invalid mac address change\n");
net_if_up(iface);
}
static void test_change_auto_neg(void)
{
struct net_if *iface = net_if_get_default();
struct ethernet_req_params params;
int ret;
params.auto_negotiation = false;
ret = net_mgmt(NET_REQUEST_ETHERNET_SET_AUTO_NEGOTIATION, iface,
&params, sizeof(struct ethernet_req_params));
zassert_equal(ret, 0, "invalid auto negotiation change\n");
}
static void test_change_to_same_auto_neg(void)
{
struct net_if *iface = net_if_get_default();
struct ethernet_req_params params;
int ret;
params.auto_negotiation = false;
ret = net_mgmt(NET_REQUEST_ETHERNET_SET_AUTO_NEGOTIATION, iface,
&params, sizeof(struct ethernet_req_params));
zassert_not_equal(ret, 0,
"invalid change to already auto negotiation\n");
}
static void test_change_link(void)
{
struct net_if *iface = net_if_get_default();
struct ethernet_req_params params = { 0 };
int ret;
params.l.link_100bt = true;
ret = net_mgmt(NET_REQUEST_ETHERNET_SET_LINK, iface,
&params, sizeof(struct ethernet_req_params));
zassert_equal(ret, 0, "invalid link change\n");
}
static void test_change_same_link(void)
{
struct net_if *iface = net_if_get_default();
struct ethernet_req_params params = { 0 };
int ret;
params.l.link_100bt = true;
ret = net_mgmt(NET_REQUEST_ETHERNET_SET_LINK, iface,
&params, sizeof(struct ethernet_req_params));
zassert_not_equal(ret, 0, "invalid same link change\n");
}
static void test_change_unsupported_link(void)
{
struct net_if *iface = net_if_get_default();
struct ethernet_req_params params = { 0 };
int ret;
params.l.link_1000bt = true;
ret = net_mgmt(NET_REQUEST_ETHERNET_SET_LINK, iface,
&params, sizeof(struct ethernet_req_params));
zassert_not_equal(ret, 0, "invalid change to unsupported link\n");
}
static void test_change_duplex(void)
{
struct net_if *iface = net_if_get_default();
struct ethernet_req_params params;
int ret;
params.full_duplex = false;
ret = net_mgmt(NET_REQUEST_ETHERNET_SET_DUPLEX, iface,
&params, sizeof(struct ethernet_req_params));
zassert_equal(ret, 0, "invalid duplex change\n");
}
static void test_change_same_duplex(void)
{
struct net_if *iface = net_if_get_default();
struct ethernet_req_params params;
int ret;
params.full_duplex = false;
ret = net_mgmt(NET_REQUEST_ETHERNET_SET_DUPLEX, iface,
&params, sizeof(struct ethernet_req_params));
zassert_not_equal(ret, 0, "invalid change to already set duplex\n");
}
void test_main(void)
{
ztest_test_suite(ethernet_mgmt_test,
ztest_unit_test(test_change_mac_when_up),
ztest_unit_test(test_change_mac_when_down),
ztest_unit_test(test_change_auto_neg),
ztest_unit_test(test_change_to_same_auto_neg),
ztest_unit_test(test_change_link),
ztest_unit_test(test_change_same_link),
ztest_unit_test(test_change_unsupported_link),
ztest_unit_test(test_change_duplex),
ztest_unit_test(test_change_same_duplex));
ztest_run_test_suite(ethernet_mgmt_test);
}