1 /*
2  * Copyright (c) 2018 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(net_echo_server_sample, LOG_LEVEL_DBG);
9 
10 #include <zephyr/kernel.h>
11 
12 #include <zephyr/net/ethernet.h>
13 
14 /* User data for the interface callback */
15 struct ud {
16 	struct net_if *first;
17 	struct net_if *second;
18 	struct net_if *eth;
19 };
20 
iface_cb(struct net_if * iface,void * user_data)21 static void iface_cb(struct net_if *iface, void *user_data)
22 {
23 	struct ud *ud = user_data;
24 
25 	if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET) && ud->eth == NULL) {
26 		ud->eth = iface;
27 		return;
28 	}
29 
30 	if (net_if_l2(iface) != &NET_L2_GET_NAME(VIRTUAL)) {
31 		return;
32 	}
33 
34 	if (!ud->first) {
35 		ud->first = iface;
36 		return;
37 	}
38 
39 	if (!ud->second) {
40 		ud->second = iface;
41 		return;
42 	}
43 }
44 
setup_iface(struct net_if * iface,struct net_if * vlan,const char * ipv6_addr,const char * ipv4_addr,const char * netmask,uint16_t vlan_tag)45 static int setup_iface(struct net_if *iface, struct net_if *vlan,
46 		       const char *ipv6_addr, const char *ipv4_addr,
47 		       const char *netmask, uint16_t vlan_tag)
48 {
49 	struct net_if_addr *ifaddr;
50 	struct in_addr addr4;
51 	struct in6_addr addr6;
52 	int ret;
53 
54 	ret = net_eth_vlan_enable(iface, vlan_tag);
55 	if (ret < 0) {
56 		LOG_ERR("Cannot enable VLAN for tag %d (%d)", vlan_tag, ret);
57 	}
58 
59 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
60 		if (net_addr_pton(AF_INET6, ipv6_addr, &addr6)) {
61 			LOG_ERR("Invalid address: %s", ipv6_addr);
62 			return -EINVAL;
63 		}
64 
65 		ifaddr = net_if_ipv6_addr_add(vlan, &addr6,
66 					      NET_ADDR_MANUAL, 0);
67 		if (!ifaddr) {
68 			LOG_ERR("Cannot add %s to interface %p",
69 				ipv6_addr, vlan);
70 			return -EINVAL;
71 		}
72 	}
73 
74 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
75 		if (net_addr_pton(AF_INET, ipv4_addr, &addr4)) {
76 			LOG_ERR("Invalid address: %s", ipv4_addr);
77 			return -EINVAL;
78 		}
79 
80 		ifaddr = net_if_ipv4_addr_add(vlan, &addr4,
81 					      NET_ADDR_MANUAL, 0);
82 		if (!ifaddr) {
83 			LOG_ERR("Cannot add %s to interface %p",
84 				ipv4_addr, vlan);
85 			return -EINVAL;
86 		}
87 
88 		if (netmask && netmask[0]) {
89 			struct in_addr nm;
90 
91 			if (net_addr_pton(AF_INET, netmask, &nm)) {
92 				LOG_ERR("Invalid netmask: %s", ipv4_addr);
93 				return -EINVAL;
94 			}
95 
96 			net_if_ipv4_set_netmask_by_addr(vlan, &addr4, &nm);
97 		}
98 	}
99 
100 	LOG_DBG("Interface %p VLAN tag %d setup done.", vlan, vlan_tag);
101 
102 	return 0;
103 }
104 
init_vlan(void)105 int init_vlan(void)
106 {
107 	struct ud ud;
108 	int ret;
109 
110 	memset(&ud, 0, sizeof(ud));
111 
112 	net_if_foreach(iface_cb, &ud);
113 
114 	/* This sample has two VLANs. For the second one we need to manually
115 	 * create IP address for this test. But first the VLAN needs to be
116 	 * added to the interface so that IPv6 DAD can work properly.
117 	 */
118 	ret = setup_iface(ud.eth, ud.first,
119 			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR,
120 			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR,
121 			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_NETMASK,
122 			  CONFIG_NET_SAMPLE_IFACE2_VLAN_TAG);
123 	if (ret < 0) {
124 		return ret;
125 	}
126 
127 	ret = setup_iface(ud.eth, ud.second,
128 			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV6_ADDR,
129 			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_ADDR,
130 			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_NETMASK,
131 			  CONFIG_NET_SAMPLE_IFACE3_VLAN_TAG);
132 	if (ret < 0) {
133 		return ret;
134 	}
135 
136 	return 0;
137 }
138