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_REGISTER(net_vlan_sample, LOG_LEVEL_DBG);
9 
10 #include <zephyr/kernel.h>
11 #include <errno.h>
12 
13 #include <zephyr/net/net_core.h>
14 #include <zephyr/net/net_l2.h>
15 #include <zephyr/net/net_if.h>
16 #include <zephyr/net/ethernet.h>
17 
18 struct ud {
19 	struct net_if *first;
20 	struct net_if *second;
21 };
22 
iface_cb(struct net_if * iface,void * user_data)23 static void iface_cb(struct net_if *iface, void *user_data)
24 {
25 	struct ud *ud = user_data;
26 
27 	if (net_if_l2(iface) != &NET_L2_GET_NAME(VIRTUAL)) {
28 		return;
29 	}
30 
31 	if (ud->first == NULL) {
32 		ud->first = iface;
33 		return;
34 	}
35 
36 	ud->second = iface;
37 }
38 
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)39 static int setup_iface(struct net_if *iface, struct net_if *vlan,
40 		       const char *ipv6_addr, const char *ipv4_addr,
41 		       const char *netmask, uint16_t vlan_tag)
42 {
43 	struct net_if_addr *ifaddr;
44 	struct in_addr addr4;
45 	struct in6_addr addr6, netaddr6;
46 	int ret;
47 
48 	ret = net_eth_vlan_enable(iface, vlan_tag);
49 	if (ret < 0) {
50 		LOG_ERR("Cannot enable VLAN for tag %d (%d)", vlan_tag, ret);
51 	}
52 
53 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
54 		if (net_addr_pton(AF_INET6, ipv6_addr, &addr6)) {
55 			LOG_ERR("Invalid address: %s", ipv6_addr);
56 			return -EINVAL;
57 		}
58 
59 		ifaddr = net_if_ipv6_addr_add(vlan, &addr6,
60 					      NET_ADDR_MANUAL, 0);
61 		if (!ifaddr) {
62 			LOG_ERR("Cannot add %s to interface %p",
63 				ipv6_addr, vlan);
64 			return -EINVAL;
65 		}
66 
67 		net_ipv6_addr_prefix_mask((uint8_t *)&addr6,
68 					  (uint8_t *)&netaddr6,
69 					  CONFIG_NET_SAMPLE_IFACE_MY_IPV6_PREFIXLEN);
70 
71 		if (!net_if_ipv6_prefix_add(vlan, &netaddr6,
72 					    CONFIG_NET_SAMPLE_IFACE_MY_IPV6_PREFIXLEN,
73 					    (uint32_t)0xffffffff)) {
74 			LOG_ERR("Cannot add %s with prefix_len %d to interface %p",
75 				ipv6_addr,
76 				CONFIG_NET_SAMPLE_IFACE_MY_IPV6_PREFIXLEN,
77 				vlan);
78 			return -EINVAL;
79 		}
80 	}
81 
82 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
83 		if (net_addr_pton(AF_INET, ipv4_addr, &addr4)) {
84 			LOG_ERR("Invalid address: %s", ipv4_addr);
85 			return -EINVAL;
86 		}
87 
88 		ifaddr = net_if_ipv4_addr_add(vlan, &addr4,
89 					      NET_ADDR_MANUAL, 0);
90 		if (!ifaddr) {
91 			LOG_ERR("Cannot add %s to interface %p",
92 				ipv4_addr, vlan);
93 			return -EINVAL;
94 		}
95 
96 		if (netmask && netmask[0]) {
97 			struct in_addr nm;
98 
99 			if (net_addr_pton(AF_INET, netmask, &nm)) {
100 				LOG_ERR("Invalid netmask: %s", ipv4_addr);
101 				return -EINVAL;
102 			}
103 
104 			net_if_ipv4_set_netmask_by_addr(vlan, &addr4, &nm);
105 		}
106 	}
107 
108 	LOG_DBG("Interface %p VLAN tag %d setup done.", vlan, vlan_tag);
109 
110 	return 0;
111 }
112 
init_app(void)113 static int init_app(void)
114 {
115 	struct net_if *iface;
116 	struct ud ud;
117 	int ret;
118 
119 	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET));
120 	if (!iface) {
121 		LOG_ERR("No ethernet interfaces found.");
122 		return -ENOENT;
123 	}
124 
125 	memset(&ud, 0, sizeof(ud));
126 
127 	net_if_foreach(iface_cb, &ud);
128 
129 	ret = setup_iface(iface, ud.first,
130 			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR,
131 			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR,
132 			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_NETMASK,
133 			  CONFIG_NET_SAMPLE_IFACE2_VLAN_TAG);
134 	if (ret < 0) {
135 		return ret;
136 	}
137 
138 	ret = setup_iface(iface, ud.second,
139 			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV6_ADDR,
140 			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_ADDR,
141 			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_NETMASK,
142 			  CONFIG_NET_SAMPLE_IFACE3_VLAN_TAG);
143 	if (ret < 0) {
144 		return ret;
145 	}
146 
147 	/* Bring up the VLAN interface automatically */
148 	net_if_up(ud.first);
149 	net_if_up(ud.second);
150 
151 	return ret;
152 }
153 
main(void)154 int main(void)
155 {
156 	init_app();
157 	return 0;
158 }
159