1 /*
2  * Copyright (c) 2020 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(net_txtime_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 };
19 
iface_cb(struct net_if * iface,void * user_data)20 static void iface_cb(struct net_if *iface, void *user_data)
21 {
22 	struct ud *ud = user_data;
23 
24 	if (net_if_l2(iface) != &NET_L2_GET_NAME(VIRTUAL)) {
25 		return;
26 	}
27 
28 	if (!ud->first) {
29 		ud->first = iface;
30 		return;
31 	}
32 
33 	if (!ud->second) {
34 		ud->second = iface;
35 		return;
36 	}
37 }
38 
setup_iface(struct net_if * eth_iface,struct net_if * iface,const char * ipv6_addr,const char * ipv4_addr,uint16_t vlan_tag)39 static int setup_iface(struct net_if *eth_iface,
40 		       struct net_if *iface,
41 		       const char *ipv6_addr,
42 		       const char *ipv4_addr,
43 		       uint16_t vlan_tag)
44 {
45 	struct net_if_addr *ifaddr;
46 	struct in_addr addr4;
47 	struct in6_addr addr6;
48 	int ret;
49 
50 	if (!iface) {
51 		LOG_DBG("VLAN interface not set");
52 		return -ENOENT;
53 	}
54 
55 	ret = net_eth_vlan_enable(eth_iface, vlan_tag);
56 	if (ret < 0) {
57 		LOG_ERR("Cannot enable VLAN for tag %d (%d)", vlan_tag, ret);
58 	}
59 
60 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
61 		if (net_addr_pton(AF_INET6, ipv6_addr, &addr6)) {
62 			LOG_ERR("Invalid address: %s", ipv6_addr);
63 			return -EINVAL;
64 		}
65 
66 		ifaddr = net_if_ipv6_addr_add(iface, &addr6,
67 					      NET_ADDR_MANUAL, 0);
68 		if (!ifaddr) {
69 			LOG_ERR("Cannot add %s to interface %p",
70 				ipv6_addr, iface);
71 			return -EINVAL;
72 		}
73 	}
74 
75 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
76 		if (net_addr_pton(AF_INET, ipv4_addr, &addr4)) {
77 			LOG_ERR("Invalid address: %s", ipv6_addr);
78 			return -EINVAL;
79 		}
80 
81 		ifaddr = net_if_ipv4_addr_add(iface, &addr4,
82 					      NET_ADDR_MANUAL, 0);
83 		if (!ifaddr) {
84 			LOG_ERR("Cannot add %s to interface %p",
85 				ipv4_addr, iface);
86 			return -EINVAL;
87 		}
88 	}
89 
90 	LOG_DBG("Interface %p VLAN tag %d setup done.", iface, vlan_tag);
91 
92 	return 0;
93 }
94 
init_vlan(void)95 int init_vlan(void)
96 {
97 	struct net_if *iface;
98 	enum ethernet_hw_caps caps;
99 	struct ud ud;
100 	int ret;
101 
102 	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET));
103 	if (!iface) {
104 		LOG_ERR("No ethernet interfaces found.");
105 		return -ENOENT;
106 	}
107 
108 	memset(&ud, 0, sizeof(ud));
109 
110 	net_if_foreach(iface_cb, &ud);
111 
112 	caps = net_eth_get_hw_capabilities(iface);
113 	if (!(caps & ETHERNET_HW_VLAN)) {
114 		LOG_DBG("Interface %p does not support %s", iface, "VLAN");
115 		return -ENOENT;
116 	}
117 
118 	ret = setup_iface(iface, ud.first,
119 			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV6_ADDR,
120 			  CONFIG_NET_SAMPLE_IFACE2_MY_IPV4_ADDR,
121 			  CONFIG_NET_SAMPLE_IFACE2_VLAN_TAG);
122 	if (ret < 0) {
123 		return ret;
124 	}
125 
126 	ret = setup_iface(iface, ud.second,
127 			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV6_ADDR,
128 			  CONFIG_NET_SAMPLE_IFACE3_MY_IPV4_ADDR,
129 			  CONFIG_NET_SAMPLE_IFACE3_VLAN_TAG);
130 	if (ret < 0) {
131 		return ret;
132 	}
133 
134 	/* Bring up the VLAN interface automatically */
135 	net_if_up(ud.first);
136 	net_if_up(ud.second);
137 
138 	return 0;
139 }
140