1 /*
2  * Copyright (c) 2020 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <logging/log.h>
8 LOG_MODULE_DECLARE(net_txtime_sample, LOG_LEVEL_DBG);
9 
10 #include <zephyr.h>
11 
12 #include <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 *third;
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)) {
26 		return;
27 	}
28 
29 	if (!ud->first) {
30 		ud->first = iface;
31 		return;
32 	}
33 
34 	if (!ud->second) {
35 		ud->second = iface;
36 		return;
37 	}
38 
39 	if (!ud->third) {
40 		ud->third = iface;
41 		return;
42 	}
43 }
44 
setup_iface(struct net_if * iface,const char * ipv6_addr,const char * ipv4_addr,uint16_t vlan_tag)45 static int setup_iface(struct net_if *iface, const char *ipv6_addr,
46 		       const char *ipv4_addr, uint16_t vlan_tag)
47 {
48 	struct net_if_addr *ifaddr;
49 	struct in_addr addr4;
50 	struct in6_addr addr6;
51 	int ret;
52 
53 	if (!iface) {
54 		LOG_DBG("VLAN interface not set");
55 		return -ENOENT;
56 	}
57 
58 	ret = net_eth_vlan_enable(iface, vlan_tag);
59 	if (ret < 0) {
60 		LOG_ERR("Cannot enable VLAN for tag %d (%d)", vlan_tag, ret);
61 	}
62 
63 	if (IS_ENABLED(CONFIG_NET_IPV6)) {
64 		if (net_addr_pton(AF_INET6, ipv6_addr, &addr6)) {
65 			LOG_ERR("Invalid address: %s", ipv6_addr);
66 			return -EINVAL;
67 		}
68 
69 		ifaddr = net_if_ipv6_addr_add(iface, &addr6,
70 					      NET_ADDR_MANUAL, 0);
71 		if (!ifaddr) {
72 			LOG_ERR("Cannot add %s to interface %p",
73 				ipv6_addr, iface);
74 			return -EINVAL;
75 		}
76 	}
77 
78 	if (IS_ENABLED(CONFIG_NET_IPV4)) {
79 		if (net_addr_pton(AF_INET, ipv4_addr, &addr4)) {
80 			LOG_ERR("Invalid address: %s", ipv6_addr);
81 			return -EINVAL;
82 		}
83 
84 		ifaddr = net_if_ipv4_addr_add(iface, &addr4,
85 					      NET_ADDR_MANUAL, 0);
86 		if (!ifaddr) {
87 			LOG_ERR("Cannot add %s to interface %p",
88 				ipv4_addr, iface);
89 			return -EINVAL;
90 		}
91 	}
92 
93 	LOG_DBG("Interface %p VLAN tag %d setup done.", iface, vlan_tag);
94 
95 	return 0;
96 }
97 
init_vlan(void)98 int init_vlan(void)
99 {
100 	enum ethernet_hw_caps caps;
101 	struct ud ud;
102 	int ret;
103 
104 	memset(&ud, 0, sizeof(ud));
105 
106 	net_if_foreach(iface_cb, &ud);
107 
108 	caps = net_eth_get_hw_capabilities(ud.first);
109 	if (!(caps & ETHERNET_HW_VLAN)) {
110 		LOG_DBG("Interface %p does not support %s", ud.first, "VLAN");
111 		return -ENOENT;
112 	}
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.second,
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(ud.third,
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 	return 0;
135 }
136