1 /*
2  * Copyright 2022 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(nxp_s32_netc_sample, LOG_LEVEL_DBG);
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/net/net_core.h>
12 #include <zephyr/net/net_if.h>
13 #include <zephyr/net/net_mgmt.h>
14 
15 #define PSI_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_netc_psi)
16 #define VSI_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_netc_vsi)
17 
18 static K_SEM_DEFINE(iface_up, 0, 1);
19 
setup_iface(struct net_if * iface,const char * ipv6_addr,const char * ipv4_addr,const char * netmask)20 static int setup_iface(struct net_if *iface, const char *ipv6_addr,
21 		       const char *ipv4_addr, const char *netmask)
22 {
23 	struct net_if_addr *ifaddr;
24 	struct in_addr addr4;
25 	struct in6_addr addr6;
26 
27 	LOG_INF("Configuring iface %d (%p)", net_if_get_by_iface(iface), iface);
28 
29 	if (IS_ENABLED(CONFIG_NET_IPV6) && net_if_flag_is_set(iface, NET_IF_IPV6)) {
30 		if (net_addr_pton(AF_INET6, ipv6_addr, &addr6)) {
31 			LOG_ERR("Invalid address: %s", ipv6_addr);
32 			return -EINVAL;
33 		}
34 
35 		ifaddr = net_if_ipv6_addr_add(iface, &addr6, NET_ADDR_MANUAL, 0);
36 		if (!ifaddr) {
37 			LOG_ERR("Cannot add %s to interface %p", ipv6_addr, iface);
38 			return -EINVAL;
39 		}
40 		LOG_INF("IPv6 address: %s", ipv6_addr);
41 	}
42 
43 	if (IS_ENABLED(CONFIG_NET_IPV4) && net_if_flag_is_set(iface, NET_IF_IPV4)) {
44 		if (net_addr_pton(AF_INET, ipv4_addr, &addr4)) {
45 			LOG_ERR("Invalid address: %s", ipv4_addr);
46 			return -EINVAL;
47 		}
48 
49 		ifaddr = net_if_ipv4_addr_add(iface, &addr4, NET_ADDR_MANUAL, 0);
50 		if (!ifaddr) {
51 			LOG_ERR("Cannot add %s to interface %p", ipv4_addr, iface);
52 			return -EINVAL;
53 		}
54 		LOG_INF("IPv4 address: %s", ipv4_addr);
55 
56 		if (netmask && netmask[0]) {
57 			struct in_addr nm;
58 
59 			if (net_addr_pton(AF_INET, netmask, &nm)) {
60 				LOG_ERR("Invalid netmask: %s", netmask);
61 				return -EINVAL;
62 			}
63 
64 			net_if_ipv4_set_netmask_by_addr(iface, &addr4, &nm);
65 		}
66 	}
67 
68 	return 0;
69 }
70 
iface_up_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)71 static void iface_up_handler(struct net_mgmt_event_callback *cb,
72 			     uint32_t mgmt_event, struct net_if *iface)
73 {
74 	if (mgmt_event == NET_EVENT_IF_UP) {
75 		k_sem_give(&iface_up);
76 	}
77 }
78 
wait_for_iface(struct net_if * iface)79 static void wait_for_iface(struct net_if *iface)
80 {
81 	struct net_mgmt_event_callback iface_up_cb;
82 
83 	if (net_if_is_up(iface)) {
84 		return;
85 	}
86 
87 	net_mgmt_init_event_callback(&iface_up_cb, iface_up_handler, NET_EVENT_IF_UP);
88 	net_mgmt_add_event_callback(&iface_up_cb);
89 
90 	LOG_INF("Waiting for iface %d to come up", net_if_get_by_iface(iface));
91 	k_sem_take(&iface_up, K_FOREVER);
92 
93 	net_mgmt_del_event_callback(&iface_up_cb);
94 }
95 
main(void)96 int main(void)
97 {
98 	struct net_if *iface;
99 
100 	LOG_INF("Starting sample");
101 
102 	iface = net_if_lookup_by_dev(DEVICE_DT_GET(PSI_NODE));
103 	if (iface) {
104 		/* Wait for PSI iface to come up before attempting configuration */
105 		wait_for_iface(iface);
106 		setup_iface(iface,
107 			    CONFIG_NET_CONFIG_MY_IPV6_ADDR,
108 			    CONFIG_NET_CONFIG_MY_IPV4_ADDR,
109 			    CONFIG_NET_CONFIG_MY_IPV4_NETMASK);
110 	}
111 
112 #if DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_netc_vsi)
113 	iface = net_if_lookup_by_dev(DEVICE_DT_GET(VSI_NODE));
114 	if (iface) {
115 		setup_iface(iface,
116 			    CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR,
117 			    CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR,
118 			    CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_NETMASK);
119 	}
120 #endif /* DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_netc_vsi)*/
121 	return 0;
122 }
123