1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2020 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/kernel.h>
10 #include <zephyr/linker/sections.h>
11 #include <zephyr/pm/device.h>
12 #include <zephyr/ztest.h>
13 #include <zephyr/random/random.h>
14
15 #include <zephyr/net/ethernet.h>
16 #include <zephyr/net/dummy.h>
17 #include <zephyr/net/net_if.h>
18 #include <zephyr/net/socket.h>
19
20 struct fake_dev_context {
21 uint8_t mac_addr[sizeof(struct net_eth_addr)];
22 struct net_if *iface;
23 };
24
fake_dev_pm_action(const struct device * dev,enum pm_device_action action)25 static int fake_dev_pm_action(const struct device *dev,
26 enum pm_device_action action)
27 {
28 struct fake_dev_context *ctx = dev->data;
29 int ret;
30
31 switch (action) {
32 case PM_DEVICE_ACTION_SUSPEND:
33 ret = net_if_suspend(ctx->iface);
34 if (ret == -EBUSY) {
35 goto out;
36 }
37 break;
38 case PM_DEVICE_ACTION_RESUME:
39 ret = net_if_resume(ctx->iface);
40 break;
41 default:
42 ret = -ENOTSUP;
43 break;
44 }
45
46 out:
47
48 return ret;
49 }
50
51
fake_dev_send(const struct device * dev,struct net_pkt * pkt)52 static int fake_dev_send(const struct device *dev, struct net_pkt *pkt)
53 {
54 ARG_UNUSED(dev);
55 ARG_UNUSED(pkt);
56
57 return 0;
58 }
59
fake_dev_get_mac(struct fake_dev_context * ctx)60 static uint8_t *fake_dev_get_mac(struct fake_dev_context *ctx)
61 {
62 if (ctx->mac_addr[2] == 0x00) {
63 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
64 ctx->mac_addr[0] = 0x00;
65 ctx->mac_addr[1] = 0x00;
66 ctx->mac_addr[2] = 0x5E;
67 ctx->mac_addr[3] = 0x00;
68 ctx->mac_addr[4] = 0x53;
69 ctx->mac_addr[5] = sys_rand8_get();
70 }
71
72 return ctx->mac_addr;
73 }
74
fake_dev_iface_init(struct net_if * iface)75 static void fake_dev_iface_init(struct net_if *iface)
76 {
77 const struct device *dev = net_if_get_device(iface);
78 struct fake_dev_context *ctx = dev->data;
79 uint8_t *mac = fake_dev_get_mac(ctx);
80
81 net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET);
82
83 ctx->iface = iface;
84 }
85
86 struct fake_dev_context fake_dev_context_data;
87
88 static struct dummy_api fake_dev_if_api = {
89 .iface_api.init = fake_dev_iface_init,
90 .send = fake_dev_send,
91 };
92
93 #define _ETH_L2_LAYER DUMMY_L2
94 #define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)
95
96 PM_DEVICE_DEFINE(fake_dev, fake_dev_pm_action);
97
98 NET_DEVICE_INIT(fake_dev, "fake_dev",
99 NULL, PM_DEVICE_GET(fake_dev),
100 &fake_dev_context_data, NULL,
101 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
102 &fake_dev_if_api, _ETH_L2_LAYER, _ETH_L2_CTX_TYPE, 127);
103
test_setup(void)104 void *test_setup(void)
105 {
106 struct net_if *iface;
107 struct in_addr in4addr_my = { { { 192, 168, 0, 2 } } };
108 struct net_if_addr *ifaddr;
109
110 iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
111
112 net_if_up(iface);
113
114 ifaddr = net_if_ipv4_addr_add(iface, &in4addr_my, NET_ADDR_MANUAL, 0);
115 zassert_not_null(ifaddr, "Could not add iface address");
116 return NULL;
117 }
118
ZTEST(test_net_pm_test_suite,test_pm)119 ZTEST(test_net_pm_test_suite, test_pm)
120 {
121 struct net_if *iface =
122 net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
123 const struct device *dev = net_if_get_device(iface);
124 char data[] = "some data";
125 struct sockaddr_in addr4;
126 int sock;
127 int ret;
128
129 addr4.sin_family = AF_INET;
130 addr4.sin_port = htons(12345);
131 zsock_inet_pton(AF_INET, "192.168.0.1", &addr4.sin_addr);
132
133 sock = zsock_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
134 zassert_true(sock >= 0, "Could not open socket");
135
136 zassert_false(net_if_is_suspended(iface), "net iface is not suspended");
137
138 /* Let's send some data, it should go through */
139 ret = zsock_sendto(sock, data, ARRAY_SIZE(data), 0,
140 (struct sockaddr *)&addr4, sizeof(struct sockaddr_in));
141 zassert_true(ret > 0, "Could not send data");
142
143 /* Let's make sure net stack's thread gets ran, or setting PM state
144 * might return -EBUSY instead
145 */
146 k_yield();
147
148 ret = pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND);
149 zassert_true(ret == 0, "Could not set state");
150
151 zassert_true(net_if_is_suspended(iface), "net iface is not suspended");
152
153 /* Let's try to suspend it again, it should fail relevantly */
154 ret = pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND);
155 zassert_true(ret == -EALREADY, "Could change state");
156
157 zassert_true(net_if_is_suspended(iface), "net iface is not suspended");
158
159 /* Let's send some data, it should fail relevantly */
160 ret = zsock_sendto(sock, data, ARRAY_SIZE(data), 0,
161 (struct sockaddr *)&addr4, sizeof(struct sockaddr_in));
162 zassert_true(ret < 0, "Could send data");
163
164 ret = pm_device_action_run(dev, PM_DEVICE_ACTION_RESUME);
165 zassert_true(ret == 0, "Could not set state");
166
167 zassert_false(net_if_is_suspended(iface), "net iface is suspended");
168
169 ret = pm_device_action_run(dev, PM_DEVICE_ACTION_RESUME);
170 zassert_true(ret == -EALREADY, "Could change state");
171
172 /* Let's send some data, it should go through */
173 ret = zsock_sendto(sock, data, ARRAY_SIZE(data), 0,
174 (struct sockaddr *)&addr4, sizeof(struct sockaddr_in));
175 zassert_true(ret > 0, "Could not send data");
176
177 zsock_close(sock);
178 }
179
180 ZTEST_SUITE(test_net_pm_test_suite, NULL, test_setup, NULL, NULL, NULL);
181