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