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