xref: /freebsd/sbin/ifconfig/ifvxlan.c (revision 32e86a82f54826f14ea381affa6674db3aa3b5ae)
1007054f0SBryan Venteicher /*-
2007054f0SBryan Venteicher  * Copyright (c) 2014, Bryan Venteicher <bryanv@FreeBSD.org>
3007054f0SBryan Venteicher  * All rights reserved.
4007054f0SBryan Venteicher  *
5007054f0SBryan Venteicher  * Redistribution and use in source and binary forms, with or without
6007054f0SBryan Venteicher  * modification, are permitted provided that the following conditions
7007054f0SBryan Venteicher  * are met:
8007054f0SBryan Venteicher  * 1. Redistributions of source code must retain the above copyright
9007054f0SBryan Venteicher  *    notice unmodified, this list of conditions, and the following
10007054f0SBryan Venteicher  *    disclaimer.
11007054f0SBryan Venteicher  * 2. Redistributions in binary form must reproduce the above copyright
12007054f0SBryan Venteicher  *    notice, this list of conditions and the following disclaimer in the
13007054f0SBryan Venteicher  *    documentation and/or other materials provided with the distribution.
14007054f0SBryan Venteicher  *
15007054f0SBryan Venteicher  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16007054f0SBryan Venteicher  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17007054f0SBryan Venteicher  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18007054f0SBryan Venteicher  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19007054f0SBryan Venteicher  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20007054f0SBryan Venteicher  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21007054f0SBryan Venteicher  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22007054f0SBryan Venteicher  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23007054f0SBryan Venteicher  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24007054f0SBryan Venteicher  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25007054f0SBryan Venteicher  */
26007054f0SBryan Venteicher 
27007054f0SBryan Venteicher #include <sys/param.h>
28007054f0SBryan Venteicher #include <sys/ioctl.h>
29007054f0SBryan Venteicher #include <sys/socket.h>
30007054f0SBryan Venteicher #include <sys/sockio.h>
31007054f0SBryan Venteicher 
32007054f0SBryan Venteicher #include <stdlib.h>
33007054f0SBryan Venteicher #include <stdint.h>
34007054f0SBryan Venteicher #include <unistd.h>
35007054f0SBryan Venteicher #include <netdb.h>
36007054f0SBryan Venteicher 
37007054f0SBryan Venteicher #include <net/ethernet.h>
38007054f0SBryan Venteicher #include <net/if.h>
39007054f0SBryan Venteicher #include <net/if_vxlan.h>
40007054f0SBryan Venteicher #include <net/route.h>
41007054f0SBryan Venteicher #include <netinet/in.h>
42007054f0SBryan Venteicher 
43007054f0SBryan Venteicher #include <ctype.h>
44007054f0SBryan Venteicher #include <stdio.h>
45007054f0SBryan Venteicher #include <string.h>
46007054f0SBryan Venteicher #include <stdlib.h>
47007054f0SBryan Venteicher #include <unistd.h>
48007054f0SBryan Venteicher #include <err.h>
49007054f0SBryan Venteicher #include <errno.h>
50007054f0SBryan Venteicher 
51007054f0SBryan Venteicher #include "ifconfig.h"
52007054f0SBryan Venteicher 
53007054f0SBryan Venteicher static struct ifvxlanparam params = {
54007054f0SBryan Venteicher 	.vxlp_vni	= VXLAN_VNI_MAX,
55007054f0SBryan Venteicher };
56007054f0SBryan Venteicher 
57007054f0SBryan Venteicher static int
get_val(const char * cp,u_long * valp)58007054f0SBryan Venteicher get_val(const char *cp, u_long *valp)
59007054f0SBryan Venteicher {
60007054f0SBryan Venteicher 	char *endptr;
61007054f0SBryan Venteicher 	u_long val;
62007054f0SBryan Venteicher 
63007054f0SBryan Venteicher 	errno = 0;
64007054f0SBryan Venteicher 	val = strtoul(cp, &endptr, 0);
65007054f0SBryan Venteicher 	if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
66007054f0SBryan Venteicher 		return (-1);
67007054f0SBryan Venteicher 
68007054f0SBryan Venteicher 	*valp = val;
69007054f0SBryan Venteicher 	return (0);
70007054f0SBryan Venteicher }
71007054f0SBryan Venteicher 
72007054f0SBryan Venteicher static int
do_cmd(if_ctx * ctx,u_long op,void * arg,size_t argsize,int set)736e3a9d7fSAlexander V. Chernikov do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set)
74007054f0SBryan Venteicher {
757fa282e6SAlexander V. Chernikov 	struct ifdrv ifd = {};
76007054f0SBryan Venteicher 
777fa282e6SAlexander V. Chernikov 	strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name));
78007054f0SBryan Venteicher 	ifd.ifd_cmd = op;
79007054f0SBryan Venteicher 	ifd.ifd_len = argsize;
80007054f0SBryan Venteicher 	ifd.ifd_data = arg;
81007054f0SBryan Venteicher 
827fa282e6SAlexander V. Chernikov 	return (ioctl_ctx(ctx, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
83007054f0SBryan Venteicher }
84007054f0SBryan Venteicher 
85007054f0SBryan Venteicher static int
vxlan_exists(if_ctx * ctx)866e3a9d7fSAlexander V. Chernikov vxlan_exists(if_ctx *ctx)
87007054f0SBryan Venteicher {
88007054f0SBryan Venteicher 	struct ifvxlancfg cfg;
89007054f0SBryan Venteicher 
90007054f0SBryan Venteicher 	bzero(&cfg, sizeof(cfg));
91007054f0SBryan Venteicher 
926e3a9d7fSAlexander V. Chernikov 	return (do_cmd(ctx, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1);
93007054f0SBryan Venteicher }
94007054f0SBryan Venteicher 
95007054f0SBryan Venteicher static void
vxlan_status(if_ctx * ctx)966e3a9d7fSAlexander V. Chernikov vxlan_status(if_ctx *ctx)
97007054f0SBryan Venteicher {
98007054f0SBryan Venteicher 	struct ifvxlancfg cfg;
99007054f0SBryan Venteicher 	char src[NI_MAXHOST], dst[NI_MAXHOST];
100007054f0SBryan Venteicher 	char srcport[NI_MAXSERV], dstport[NI_MAXSERV];
101007054f0SBryan Venteicher 	struct sockaddr *lsa, *rsa;
102007054f0SBryan Venteicher 	int vni, mc, ipv6;
103007054f0SBryan Venteicher 
104007054f0SBryan Venteicher 	bzero(&cfg, sizeof(cfg));
105007054f0SBryan Venteicher 
1066e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) < 0)
107007054f0SBryan Venteicher 		return;
108007054f0SBryan Venteicher 
109007054f0SBryan Venteicher 	vni = cfg.vxlc_vni;
110007054f0SBryan Venteicher 	lsa = &cfg.vxlc_local_sa.sa;
111007054f0SBryan Venteicher 	rsa = &cfg.vxlc_remote_sa.sa;
112007054f0SBryan Venteicher 	ipv6 = rsa->sa_family == AF_INET6;
113007054f0SBryan Venteicher 
114007054f0SBryan Venteicher 	/* Just report nothing if the network identity isn't set yet. */
115007054f0SBryan Venteicher 	if (vni >= VXLAN_VNI_MAX)
116007054f0SBryan Venteicher 		return;
117007054f0SBryan Venteicher 
118007054f0SBryan Venteicher 	if (getnameinfo(lsa, lsa->sa_len, src, sizeof(src),
119007054f0SBryan Venteicher 	    srcport, sizeof(srcport), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
120007054f0SBryan Venteicher 		src[0] = srcport[0] = '\0';
121007054f0SBryan Venteicher 	if (getnameinfo(rsa, rsa->sa_len, dst, sizeof(dst),
122007054f0SBryan Venteicher 	    dstport, sizeof(dstport), NI_NUMERICHOST | NI_NUMERICSERV) != 0)
123007054f0SBryan Venteicher 		dst[0] = dstport[0] = '\0';
124007054f0SBryan Venteicher 
125007054f0SBryan Venteicher 	if (!ipv6) {
12644cd85d4SAlexander V. Chernikov 		struct sockaddr_in *sin = satosin(rsa);
127007054f0SBryan Venteicher 		mc = IN_MULTICAST(ntohl(sin->sin_addr.s_addr));
128007054f0SBryan Venteicher 	} else {
12944cd85d4SAlexander V. Chernikov 		struct sockaddr_in6 *sin6 = satosin6(rsa);
130007054f0SBryan Venteicher 		mc = IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr);
131007054f0SBryan Venteicher 	}
132007054f0SBryan Venteicher 
133007054f0SBryan Venteicher 	printf("\tvxlan vni %d", vni);
134007054f0SBryan Venteicher 	printf(" local %s%s%s:%s", ipv6 ? "[" : "", src, ipv6 ? "]" : "",
135007054f0SBryan Venteicher 	    srcport);
136007054f0SBryan Venteicher 	printf(" %s %s%s%s:%s", mc ? "group" : "remote", ipv6 ? "[" : "",
137007054f0SBryan Venteicher 	    dst, ipv6 ? "]" : "", dstport);
138007054f0SBryan Venteicher 
139c6885dbdSAlexander V. Chernikov 	if (ctx->args->verbose) {
140007054f0SBryan Venteicher 		printf("\n\t\tconfig: ");
141007054f0SBryan Venteicher 		printf("%slearning portrange %d-%d ttl %d",
142007054f0SBryan Venteicher 		    cfg.vxlc_learn ? "" : "no", cfg.vxlc_port_min,
143007054f0SBryan Venteicher 		    cfg.vxlc_port_max, cfg.vxlc_ttl);
144007054f0SBryan Venteicher 		printf("\n\t\tftable: ");
145007054f0SBryan Venteicher 		printf("cnt %d max %d timeout %d",
146007054f0SBryan Venteicher 		    cfg.vxlc_ftable_cnt, cfg.vxlc_ftable_max,
147007054f0SBryan Venteicher 		    cfg.vxlc_ftable_timeout);
148007054f0SBryan Venteicher 	}
149007054f0SBryan Venteicher 
150007054f0SBryan Venteicher 	putchar('\n');
151007054f0SBryan Venteicher }
152007054f0SBryan Venteicher 
153007054f0SBryan Venteicher #define _LOCAL_ADDR46 \
154007054f0SBryan Venteicher     (VXLAN_PARAM_WITH_LOCAL_ADDR4 | VXLAN_PARAM_WITH_LOCAL_ADDR6)
155007054f0SBryan Venteicher #define _REMOTE_ADDR46 \
156007054f0SBryan Venteicher     (VXLAN_PARAM_WITH_REMOTE_ADDR4 | VXLAN_PARAM_WITH_REMOTE_ADDR6)
157007054f0SBryan Venteicher 
158007054f0SBryan Venteicher static void
vxlan_check_params(void)159007054f0SBryan Venteicher vxlan_check_params(void)
160007054f0SBryan Venteicher {
161007054f0SBryan Venteicher 
162007054f0SBryan Venteicher 	if ((params.vxlp_with & _LOCAL_ADDR46) == _LOCAL_ADDR46)
163007054f0SBryan Venteicher 		errx(1, "cannot specify both local IPv4 and IPv6 addresses");
164007054f0SBryan Venteicher 	if ((params.vxlp_with & _REMOTE_ADDR46) == _REMOTE_ADDR46)
165007054f0SBryan Venteicher 		errx(1, "cannot specify both remote IPv4 and IPv6 addresses");
166007054f0SBryan Venteicher 	if ((params.vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR4 &&
167007054f0SBryan Venteicher 	     params.vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR6) ||
168007054f0SBryan Venteicher 	    (params.vxlp_with & VXLAN_PARAM_WITH_LOCAL_ADDR6 &&
169007054f0SBryan Venteicher 	     params.vxlp_with & VXLAN_PARAM_WITH_REMOTE_ADDR4))
170007054f0SBryan Venteicher 		errx(1, "cannot mix IPv4 and IPv6 addresses");
171007054f0SBryan Venteicher }
172007054f0SBryan Venteicher 
173007054f0SBryan Venteicher #undef _LOCAL_ADDR46
174007054f0SBryan Venteicher #undef _REMOTE_ADDR46
175007054f0SBryan Venteicher 
176007054f0SBryan Venteicher static void
vxlan_create(if_ctx * ctx,struct ifreq * ifr)17774b42611SAlexander V. Chernikov vxlan_create(if_ctx *ctx, struct ifreq *ifr)
178007054f0SBryan Venteicher {
179007054f0SBryan Venteicher 
180007054f0SBryan Venteicher 	vxlan_check_params();
181007054f0SBryan Venteicher 
182007054f0SBryan Venteicher 	ifr->ifr_data = (caddr_t) &params;
18374b42611SAlexander V. Chernikov 	ifcreate_ioctl(ctx, ifr);
184007054f0SBryan Venteicher }
185007054f0SBryan Venteicher 
1866e3a9d7fSAlexander V. Chernikov static void
setvxlan_vni(if_ctx * ctx,const char * arg,int dummy __unused)1876e3a9d7fSAlexander V. Chernikov setvxlan_vni(if_ctx *ctx, const char *arg, int dummy __unused)
188007054f0SBryan Venteicher {
189007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
190007054f0SBryan Venteicher 	u_long val;
191007054f0SBryan Venteicher 
192007054f0SBryan Venteicher 	if (get_val(arg, &val) < 0 || val >= VXLAN_VNI_MAX)
193007054f0SBryan Venteicher 		errx(1, "invalid network identifier: %s", arg);
194007054f0SBryan Venteicher 
1956e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
196007054f0SBryan Venteicher 		params.vxlp_with |= VXLAN_PARAM_WITH_VNI;
197007054f0SBryan Venteicher 		params.vxlp_vni = val;
198007054f0SBryan Venteicher 		return;
199007054f0SBryan Venteicher 	}
200007054f0SBryan Venteicher 
201007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
202007054f0SBryan Venteicher 	cmd.vxlcmd_vni = val;
203007054f0SBryan Venteicher 
2046e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0)
205007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_VNI");
206007054f0SBryan Venteicher }
207007054f0SBryan Venteicher 
2086e3a9d7fSAlexander V. Chernikov static void
setvxlan_local(if_ctx * ctx,const char * addr,int dummy __unused)2096e3a9d7fSAlexander V. Chernikov setvxlan_local(if_ctx *ctx, const char *addr, int dummy __unused)
210007054f0SBryan Venteicher {
211007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
212007054f0SBryan Venteicher 	struct addrinfo *ai;
213*cea9f49fSMateusz Guzik #if (defined INET || defined INET6)
214007054f0SBryan Venteicher 	struct sockaddr *sa;
215*cea9f49fSMateusz Guzik #endif
216007054f0SBryan Venteicher 	int error;
217007054f0SBryan Venteicher 
218007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
219007054f0SBryan Venteicher 
220007054f0SBryan Venteicher 	if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
221007054f0SBryan Venteicher 		errx(1, "error in parsing local address string: %s",
222007054f0SBryan Venteicher 		    gai_strerror(error));
223007054f0SBryan Venteicher 
224*cea9f49fSMateusz Guzik #if (defined INET || defined INET6)
225007054f0SBryan Venteicher 	sa = ai->ai_addr;
226*cea9f49fSMateusz Guzik #endif
227007054f0SBryan Venteicher 
228007054f0SBryan Venteicher 	switch (ai->ai_family) {
229007054f0SBryan Venteicher #ifdef INET
230007054f0SBryan Venteicher 	case AF_INET: {
23144cd85d4SAlexander V. Chernikov 		struct sockaddr_in *sin = satosin(sa);
232007054f0SBryan Venteicher 
23333e0d8f0SBryan Venteicher 		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
234007054f0SBryan Venteicher 			errx(1, "local address cannot be multicast");
235007054f0SBryan Venteicher 
23633e0d8f0SBryan Venteicher 		cmd.vxlcmd_sa.in4 = *sin;
237007054f0SBryan Venteicher 		break;
238007054f0SBryan Venteicher 	}
239007054f0SBryan Venteicher #endif
240007054f0SBryan Venteicher #ifdef INET6
241007054f0SBryan Venteicher 	case AF_INET6: {
24244cd85d4SAlexander V. Chernikov 		struct sockaddr_in6 *sin6 = satosin6(sa);
243007054f0SBryan Venteicher 
24433e0d8f0SBryan Venteicher 		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
245007054f0SBryan Venteicher 			errx(1, "local address cannot be multicast");
246007054f0SBryan Venteicher 
24733e0d8f0SBryan Venteicher 		cmd.vxlcmd_sa.in6 = *sin6;
248007054f0SBryan Venteicher 		break;
249007054f0SBryan Venteicher 	}
250007054f0SBryan Venteicher #endif
251007054f0SBryan Venteicher 	default:
252007054f0SBryan Venteicher 		errx(1, "local address %s not supported", addr);
253007054f0SBryan Venteicher 	}
254007054f0SBryan Venteicher 
255007054f0SBryan Venteicher 	freeaddrinfo(ai);
256007054f0SBryan Venteicher 
2576e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
258007054f0SBryan Venteicher 		if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
259007054f0SBryan Venteicher 			params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4;
26033e0d8f0SBryan Venteicher 			params.vxlp_local_sa.in4 = cmd.vxlcmd_sa.in4;
261007054f0SBryan Venteicher 		} else {
262007054f0SBryan Venteicher 			params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR6;
26333e0d8f0SBryan Venteicher 			params.vxlp_local_sa.in6 = cmd.vxlcmd_sa.in6;
264007054f0SBryan Venteicher 		}
265007054f0SBryan Venteicher 		return;
266007054f0SBryan Venteicher 	}
267007054f0SBryan Venteicher 
2686e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0)
269007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_LOCAL_ADDR");
270007054f0SBryan Venteicher }
271007054f0SBryan Venteicher 
2726e3a9d7fSAlexander V. Chernikov static void
setvxlan_remote(if_ctx * ctx,const char * addr,int dummy __unused)2736e3a9d7fSAlexander V. Chernikov setvxlan_remote(if_ctx *ctx, const char *addr, int dummy __unused)
274007054f0SBryan Venteicher {
275007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
276007054f0SBryan Venteicher 	struct addrinfo *ai;
277*cea9f49fSMateusz Guzik #if (defined INET || defined INET6)
278007054f0SBryan Venteicher 	struct sockaddr *sa;
279*cea9f49fSMateusz Guzik #endif
280007054f0SBryan Venteicher 	int error;
281007054f0SBryan Venteicher 
282007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
283007054f0SBryan Venteicher 
284007054f0SBryan Venteicher 	if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
285007054f0SBryan Venteicher 		errx(1, "error in parsing remote address string: %s",
286007054f0SBryan Venteicher 		    gai_strerror(error));
287007054f0SBryan Venteicher 
288*cea9f49fSMateusz Guzik #if (defined INET || defined INET6)
289007054f0SBryan Venteicher 	sa = ai->ai_addr;
290*cea9f49fSMateusz Guzik #endif
291007054f0SBryan Venteicher 
292007054f0SBryan Venteicher 	switch (ai->ai_family) {
293007054f0SBryan Venteicher #ifdef INET
294007054f0SBryan Venteicher 	case AF_INET: {
29544cd85d4SAlexander V. Chernikov 		struct sockaddr_in *sin = satosin(sa);
296007054f0SBryan Venteicher 
29733e0d8f0SBryan Venteicher 		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
298007054f0SBryan Venteicher 			errx(1, "remote address cannot be multicast");
299007054f0SBryan Venteicher 
30033e0d8f0SBryan Venteicher 		cmd.vxlcmd_sa.in4 = *sin;
301007054f0SBryan Venteicher 		break;
302007054f0SBryan Venteicher 	}
303007054f0SBryan Venteicher #endif
304007054f0SBryan Venteicher #ifdef INET6
305007054f0SBryan Venteicher 	case AF_INET6: {
30644cd85d4SAlexander V. Chernikov 		struct sockaddr_in6 *sin6 = satosin6(sa);
307007054f0SBryan Venteicher 
30833e0d8f0SBryan Venteicher 		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
309007054f0SBryan Venteicher 			errx(1, "remote address cannot be multicast");
310007054f0SBryan Venteicher 
31133e0d8f0SBryan Venteicher 		cmd.vxlcmd_sa.in6 = *sin6;
312007054f0SBryan Venteicher 		break;
313007054f0SBryan Venteicher 	}
314007054f0SBryan Venteicher #endif
315007054f0SBryan Venteicher 	default:
316007054f0SBryan Venteicher 		errx(1, "remote address %s not supported", addr);
317007054f0SBryan Venteicher 	}
318007054f0SBryan Venteicher 
319007054f0SBryan Venteicher 	freeaddrinfo(ai);
320007054f0SBryan Venteicher 
3216e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
322007054f0SBryan Venteicher 		if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
323007054f0SBryan Venteicher 			params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
32433e0d8f0SBryan Venteicher 			params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
325007054f0SBryan Venteicher 		} else {
326007054f0SBryan Venteicher 			params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
32733e0d8f0SBryan Venteicher 			params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
328007054f0SBryan Venteicher 		}
329007054f0SBryan Venteicher 		return;
330007054f0SBryan Venteicher 	}
331007054f0SBryan Venteicher 
3326e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
333007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
334007054f0SBryan Venteicher }
335007054f0SBryan Venteicher 
3366e3a9d7fSAlexander V. Chernikov static void
setvxlan_group(if_ctx * ctx,const char * addr,int dummy __unused)3376e3a9d7fSAlexander V. Chernikov setvxlan_group(if_ctx *ctx, const char *addr, int dummy __unused)
338007054f0SBryan Venteicher {
339007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
340007054f0SBryan Venteicher 	struct addrinfo *ai;
341*cea9f49fSMateusz Guzik #if (defined INET || defined INET6)
342007054f0SBryan Venteicher 	struct sockaddr *sa;
343*cea9f49fSMateusz Guzik #endif
344007054f0SBryan Venteicher 	int error;
345007054f0SBryan Venteicher 
346007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
347007054f0SBryan Venteicher 
348007054f0SBryan Venteicher 	if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0)
349007054f0SBryan Venteicher 		errx(1, "error in parsing group address string: %s",
350007054f0SBryan Venteicher 		    gai_strerror(error));
351007054f0SBryan Venteicher 
352*cea9f49fSMateusz Guzik #if (defined INET || defined INET6)
353007054f0SBryan Venteicher 	sa = ai->ai_addr;
354*cea9f49fSMateusz Guzik #endif
355007054f0SBryan Venteicher 
356007054f0SBryan Venteicher 	switch (ai->ai_family) {
357007054f0SBryan Venteicher #ifdef INET
358007054f0SBryan Venteicher 	case AF_INET: {
35944cd85d4SAlexander V. Chernikov 		struct sockaddr_in *sin = satosin(sa);
360007054f0SBryan Venteicher 
36133e0d8f0SBryan Venteicher 		if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
362007054f0SBryan Venteicher 			errx(1, "group address must be multicast");
363007054f0SBryan Venteicher 
36433e0d8f0SBryan Venteicher 		cmd.vxlcmd_sa.in4 = *sin;
365007054f0SBryan Venteicher 		break;
366007054f0SBryan Venteicher 	}
367007054f0SBryan Venteicher #endif
368007054f0SBryan Venteicher #ifdef INET6
369007054f0SBryan Venteicher 	case AF_INET6: {
37044cd85d4SAlexander V. Chernikov 		struct sockaddr_in6 *sin6 = satosin6(sa);
371007054f0SBryan Venteicher 
37233e0d8f0SBryan Venteicher 		if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
373007054f0SBryan Venteicher 			errx(1, "group address must be multicast");
374007054f0SBryan Venteicher 
37533e0d8f0SBryan Venteicher 		cmd.vxlcmd_sa.in6 = *sin6;
376007054f0SBryan Venteicher 		break;
377007054f0SBryan Venteicher 	}
378007054f0SBryan Venteicher #endif
379007054f0SBryan Venteicher 	default:
380007054f0SBryan Venteicher 		errx(1, "group address %s not supported", addr);
381007054f0SBryan Venteicher 	}
382007054f0SBryan Venteicher 
383007054f0SBryan Venteicher 	freeaddrinfo(ai);
384007054f0SBryan Venteicher 
3856e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
386007054f0SBryan Venteicher 		if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
387007054f0SBryan Venteicher 			params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
38833e0d8f0SBryan Venteicher 			params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
389007054f0SBryan Venteicher 		} else {
390007054f0SBryan Venteicher 			params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6;
39133e0d8f0SBryan Venteicher 			params.vxlp_remote_sa.in6 = cmd.vxlcmd_sa.in6;
392007054f0SBryan Venteicher 		}
393007054f0SBryan Venteicher 		return;
394007054f0SBryan Venteicher 	}
395007054f0SBryan Venteicher 
3966e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
397007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
398007054f0SBryan Venteicher }
399007054f0SBryan Venteicher 
4006e3a9d7fSAlexander V. Chernikov static void
setvxlan_local_port(if_ctx * ctx,const char * arg,int dummy __unused)4016e3a9d7fSAlexander V. Chernikov setvxlan_local_port(if_ctx *ctx, const char *arg, int dummy __unused)
402007054f0SBryan Venteicher {
403007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
404007054f0SBryan Venteicher 	u_long val;
405007054f0SBryan Venteicher 
406007054f0SBryan Venteicher 	if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
407007054f0SBryan Venteicher 		errx(1, "invalid local port: %s", arg);
408007054f0SBryan Venteicher 
4096e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
410007054f0SBryan Venteicher 		params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_PORT;
411007054f0SBryan Venteicher 		params.vxlp_local_port = val;
412007054f0SBryan Venteicher 		return;
413007054f0SBryan Venteicher 	}
414007054f0SBryan Venteicher 
415007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
416007054f0SBryan Venteicher 	cmd.vxlcmd_port = val;
417007054f0SBryan Venteicher 
4186e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0)
419007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_LOCAL_PORT");
420007054f0SBryan Venteicher }
421007054f0SBryan Venteicher 
4226e3a9d7fSAlexander V. Chernikov static void
setvxlan_remote_port(if_ctx * ctx,const char * arg,int dummy __unused)4236e3a9d7fSAlexander V. Chernikov setvxlan_remote_port(if_ctx *ctx, const char *arg, int dummy __unused)
424007054f0SBryan Venteicher {
425007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
426007054f0SBryan Venteicher 	u_long val;
427007054f0SBryan Venteicher 
428007054f0SBryan Venteicher 	if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
429007054f0SBryan Venteicher 		errx(1, "invalid remote port: %s", arg);
430007054f0SBryan Venteicher 
4316e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
432007054f0SBryan Venteicher 		params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_PORT;
433007054f0SBryan Venteicher 		params.vxlp_remote_port = val;
434007054f0SBryan Venteicher 		return;
435007054f0SBryan Venteicher 	}
436007054f0SBryan Venteicher 
437007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
438007054f0SBryan Venteicher 	cmd.vxlcmd_port = val;
439007054f0SBryan Venteicher 
4406e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0)
441007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_REMOTE_PORT");
442007054f0SBryan Venteicher }
443007054f0SBryan Venteicher 
4446e3a9d7fSAlexander V. Chernikov static void
setvxlan_port_range(if_ctx * ctx,const char * arg1,const char * arg2)4456e3a9d7fSAlexander V. Chernikov setvxlan_port_range(if_ctx *ctx, const char *arg1, const char *arg2)
446007054f0SBryan Venteicher {
447007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
448007054f0SBryan Venteicher 	u_long min, max;
449007054f0SBryan Venteicher 
450007054f0SBryan Venteicher 	if (get_val(arg1, &min) < 0 || min >= UINT16_MAX)
451007054f0SBryan Venteicher 		errx(1, "invalid port range minimum: %s", arg1);
452007054f0SBryan Venteicher 	if (get_val(arg2, &max) < 0 || max >= UINT16_MAX)
453007054f0SBryan Venteicher 		errx(1, "invalid port range maximum: %s", arg2);
454007054f0SBryan Venteicher 	if (max < min)
455007054f0SBryan Venteicher 		errx(1, "invalid port range");
456007054f0SBryan Venteicher 
4576e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
458007054f0SBryan Venteicher 		params.vxlp_with |= VXLAN_PARAM_WITH_PORT_RANGE;
459007054f0SBryan Venteicher 		params.vxlp_min_port = min;
460007054f0SBryan Venteicher 		params.vxlp_max_port = max;
461007054f0SBryan Venteicher 		return;
462007054f0SBryan Venteicher 	}
463007054f0SBryan Venteicher 
464007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
465007054f0SBryan Venteicher 	cmd.vxlcmd_port_min = min;
466007054f0SBryan Venteicher 	cmd.vxlcmd_port_max = max;
467007054f0SBryan Venteicher 
4686e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0)
469007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_PORT_RANGE");
470007054f0SBryan Venteicher }
471007054f0SBryan Venteicher 
4726e3a9d7fSAlexander V. Chernikov static void
setvxlan_timeout(if_ctx * ctx,const char * arg,int dummy __unused)4736e3a9d7fSAlexander V. Chernikov setvxlan_timeout(if_ctx *ctx, const char *arg, int dummy __unused)
474007054f0SBryan Venteicher {
475007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
476007054f0SBryan Venteicher 	u_long val;
477007054f0SBryan Venteicher 
478007054f0SBryan Venteicher 	if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
479007054f0SBryan Venteicher 		errx(1, "invalid timeout value: %s", arg);
480007054f0SBryan Venteicher 
4816e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
482007054f0SBryan Venteicher 		params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_TIMEOUT;
483007054f0SBryan Venteicher 		params.vxlp_ftable_timeout = val & 0xFFFFFFFF;
484007054f0SBryan Venteicher 		return;
485007054f0SBryan Venteicher 	}
486007054f0SBryan Venteicher 
487007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
488007054f0SBryan Venteicher 	cmd.vxlcmd_ftable_timeout = val & 0xFFFFFFFF;
489007054f0SBryan Venteicher 
4906e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0)
491007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_FTABLE_TIMEOUT");
492007054f0SBryan Venteicher }
493007054f0SBryan Venteicher 
4946e3a9d7fSAlexander V. Chernikov static void
setvxlan_maxaddr(if_ctx * ctx,const char * arg,int dummy __unused)4956e3a9d7fSAlexander V. Chernikov setvxlan_maxaddr(if_ctx *ctx, const char *arg, int dummy __unused)
496007054f0SBryan Venteicher {
497007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
498007054f0SBryan Venteicher 	u_long val;
499007054f0SBryan Venteicher 
500007054f0SBryan Venteicher 	if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
501007054f0SBryan Venteicher 		errx(1, "invalid maxaddr value: %s",  arg);
502007054f0SBryan Venteicher 
5036e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
504007054f0SBryan Venteicher 		params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_MAX;
505007054f0SBryan Venteicher 		params.vxlp_ftable_max = val & 0xFFFFFFFF;
506007054f0SBryan Venteicher 		return;
507007054f0SBryan Venteicher 	}
508007054f0SBryan Venteicher 
509007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
510007054f0SBryan Venteicher 	cmd.vxlcmd_ftable_max = val & 0xFFFFFFFF;
511007054f0SBryan Venteicher 
5126e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0)
513007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_FTABLE_MAX");
514007054f0SBryan Venteicher }
515007054f0SBryan Venteicher 
5166e3a9d7fSAlexander V. Chernikov static void
setvxlan_dev(if_ctx * ctx,const char * arg,int dummy __unused)5176e3a9d7fSAlexander V. Chernikov setvxlan_dev(if_ctx *ctx, const char *arg, int dummy __unused)
518007054f0SBryan Venteicher {
519007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
520007054f0SBryan Venteicher 
5216e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
522007054f0SBryan Venteicher 		params.vxlp_with |= VXLAN_PARAM_WITH_MULTICAST_IF;
523007054f0SBryan Venteicher 		strlcpy(params.vxlp_mc_ifname, arg,
524007054f0SBryan Venteicher 		    sizeof(params.vxlp_mc_ifname));
525007054f0SBryan Venteicher 		return;
526007054f0SBryan Venteicher 	}
527007054f0SBryan Venteicher 
528007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
529007054f0SBryan Venteicher 	strlcpy(cmd.vxlcmd_ifname, arg, sizeof(cmd.vxlcmd_ifname));
530007054f0SBryan Venteicher 
5316e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_MULTICAST_IF, &cmd, sizeof(cmd), 1) < 0)
532007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_MULTICAST_IF");
533007054f0SBryan Venteicher }
534007054f0SBryan Venteicher 
5356e3a9d7fSAlexander V. Chernikov static void
setvxlan_ttl(if_ctx * ctx,const char * arg,int dummy __unused)5366e3a9d7fSAlexander V. Chernikov setvxlan_ttl(if_ctx *ctx, const char *arg, int dummy __unused)
537007054f0SBryan Venteicher {
538007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
539007054f0SBryan Venteicher 	u_long val;
540007054f0SBryan Venteicher 
541007054f0SBryan Venteicher 	if (get_val(arg, &val) < 0 || val > 256)
542007054f0SBryan Venteicher 		errx(1, "invalid TTL value: %s", arg);
543007054f0SBryan Venteicher 
5446e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
545007054f0SBryan Venteicher 		params.vxlp_with |= VXLAN_PARAM_WITH_TTL;
546007054f0SBryan Venteicher 		params.vxlp_ttl = val;
547007054f0SBryan Venteicher 		return;
548007054f0SBryan Venteicher 	}
549007054f0SBryan Venteicher 
550007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
551007054f0SBryan Venteicher 	cmd.vxlcmd_ttl = val;
552007054f0SBryan Venteicher 
5536e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0)
554007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_TTL");
555007054f0SBryan Venteicher }
556007054f0SBryan Venteicher 
5576e3a9d7fSAlexander V. Chernikov static void
setvxlan_learn(if_ctx * ctx,const char * arg __unused,int d)5580c2beef7SAlexander V. Chernikov setvxlan_learn(if_ctx *ctx, const char *arg __unused, int d)
559007054f0SBryan Venteicher {
560007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
561007054f0SBryan Venteicher 
5626e3a9d7fSAlexander V. Chernikov 	if (!vxlan_exists(ctx)) {
563007054f0SBryan Venteicher 		params.vxlp_with |= VXLAN_PARAM_WITH_LEARN;
564007054f0SBryan Venteicher 		params.vxlp_learn = d;
565007054f0SBryan Venteicher 		return;
566007054f0SBryan Venteicher 	}
567007054f0SBryan Venteicher 
568007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
569007054f0SBryan Venteicher 	if (d != 0)
570007054f0SBryan Venteicher 		cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_LEARN;
571007054f0SBryan Venteicher 
5726e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0)
573007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_SET_LEARN");
574007054f0SBryan Venteicher }
575007054f0SBryan Venteicher 
576007054f0SBryan Venteicher static void
setvxlan_flush(if_ctx * ctx,const char * val __unused,int d)5776e3a9d7fSAlexander V. Chernikov setvxlan_flush(if_ctx *ctx, const char *val __unused, int d)
578007054f0SBryan Venteicher {
579007054f0SBryan Venteicher 	struct ifvxlancmd cmd;
580007054f0SBryan Venteicher 
581007054f0SBryan Venteicher 	bzero(&cmd, sizeof(cmd));
582007054f0SBryan Venteicher 	if (d != 0)
583007054f0SBryan Venteicher 		cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_FLUSH_ALL;
584007054f0SBryan Venteicher 
5856e3a9d7fSAlexander V. Chernikov 	if (do_cmd(ctx, VXLAN_CMD_FLUSH, &cmd, sizeof(cmd), 1) < 0)
586007054f0SBryan Venteicher 		err(1, "VXLAN_CMD_FLUSH");
587007054f0SBryan Venteicher }
588007054f0SBryan Venteicher 
589007054f0SBryan Venteicher static struct cmd vxlan_cmds[] = {
590007054f0SBryan Venteicher 
591f53d9723SBryan Venteicher 	DEF_CLONE_CMD_ARG("vni",                setvxlan_vni),
592c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlanid",		setvxlan_vni),
593c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlanlocal",		setvxlan_local),
594c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlanremote",	setvxlan_remote),
595c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlangroup",		setvxlan_group),
596c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlanlocalport",	setvxlan_local_port),
597c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlanremoteport",	setvxlan_remote_port),
598c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG2("vxlanportrange",	setvxlan_port_range),
599c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlantimeout",	setvxlan_timeout),
600c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlanmaxaddr",	setvxlan_maxaddr),
601007054f0SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlandev",		setvxlan_dev),
602c6e32006SBryan Venteicher 	DEF_CLONE_CMD_ARG("vxlanttl",		setvxlan_ttl),
603c6e32006SBryan Venteicher 	DEF_CLONE_CMD("vxlanlearn", 1,		setvxlan_learn),
604c6e32006SBryan Venteicher 	DEF_CLONE_CMD("-vxlanlearn", 0,		setvxlan_learn),
605007054f0SBryan Venteicher 
606f53d9723SBryan Venteicher 	DEF_CMD_ARG("vni",			setvxlan_vni),
607f53d9723SBryan Venteicher 	DEF_CMD_ARG("vxlanid",			setvxlan_vni),
608c6e32006SBryan Venteicher 	DEF_CMD_ARG("vxlanlocal",		setvxlan_local),
609c6e32006SBryan Venteicher 	DEF_CMD_ARG("vxlanremote",		setvxlan_remote),
610c6e32006SBryan Venteicher 	DEF_CMD_ARG("vxlangroup",		setvxlan_group),
611c6e32006SBryan Venteicher 	DEF_CMD_ARG("vxlanlocalport",		setvxlan_local_port),
612c6e32006SBryan Venteicher 	DEF_CMD_ARG("vxlanremoteport",		setvxlan_remote_port),
613c6e32006SBryan Venteicher 	DEF_CMD_ARG2("vxlanportrange",		setvxlan_port_range),
614c6e32006SBryan Venteicher 	DEF_CMD_ARG("vxlantimeout",		setvxlan_timeout),
615c6e32006SBryan Venteicher 	DEF_CMD_ARG("vxlanmaxaddr",		setvxlan_maxaddr),
616007054f0SBryan Venteicher 	DEF_CMD_ARG("vxlandev",			setvxlan_dev),
617c6e32006SBryan Venteicher 	DEF_CMD_ARG("vxlanttl",			setvxlan_ttl),
618c6e32006SBryan Venteicher 	DEF_CMD("vxlanlearn", 1,		setvxlan_learn),
619c6e32006SBryan Venteicher 	DEF_CMD("-vxlanlearn", 0,		setvxlan_learn),
620007054f0SBryan Venteicher 
621c6e32006SBryan Venteicher 	DEF_CMD("vxlanflush", 0,		setvxlan_flush),
622c6e32006SBryan Venteicher 	DEF_CMD("vxlanflushall", 1,		setvxlan_flush),
623830edb45SNavdeep Parhar 
624830edb45SNavdeep Parhar 	DEF_CMD("vxlanhwcsum",	IFCAP_VXLAN_HWCSUM,	setifcap),
62508992b20SJohn Baldwin 	DEF_CMD("-vxlanhwcsum",	IFCAP_VXLAN_HWCSUM,	clearifcap),
626830edb45SNavdeep Parhar 	DEF_CMD("vxlanhwtso",	IFCAP_VXLAN_HWTSO,	setifcap),
62708992b20SJohn Baldwin 	DEF_CMD("-vxlanhwtso",	IFCAP_VXLAN_HWTSO,	clearifcap),
628007054f0SBryan Venteicher };
629007054f0SBryan Venteicher 
630007054f0SBryan Venteicher static struct afswtch af_vxlan = {
631007054f0SBryan Venteicher 	.af_name		= "af_vxlan",
632007054f0SBryan Venteicher 	.af_af			= AF_UNSPEC,
633007054f0SBryan Venteicher 	.af_other_status	= vxlan_status,
634007054f0SBryan Venteicher };
635007054f0SBryan Venteicher 
636007054f0SBryan Venteicher static __constructor void
vxlan_ctor(void)637007054f0SBryan Venteicher vxlan_ctor(void)
638007054f0SBryan Venteicher {
639007054f0SBryan Venteicher 	size_t i;
640007054f0SBryan Venteicher 
641abd71050SEnji Cooper 	for (i = 0; i < nitems(vxlan_cmds); i++)
642007054f0SBryan Venteicher 		cmd_register(&vxlan_cmds[i]);
643007054f0SBryan Venteicher 	af_register(&af_vxlan);
644c7cffd65SAlexander V. Chernikov 	clone_setdefcallback_prefix("vxlan", vxlan_create);
645007054f0SBryan Venteicher }
646