1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * iplink_vxlan.c VXLAN device support
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: Stephen Hemminger <[email protected]
10*de1e4e89SAndroid Build Coastguard Worker */
11*de1e4e89SAndroid Build Coastguard Worker
12*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <net/if.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <linux/ip.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_link.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
19*de1e4e89SAndroid Build Coastguard Worker
20*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
21*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
22*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
23*de1e4e89SAndroid Build Coastguard Worker
24*de1e4e89SAndroid Build Coastguard Worker #define VXLAN_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0)
25*de1e4e89SAndroid Build Coastguard Worker
print_explain(FILE * f)26*de1e4e89SAndroid Build Coastguard Worker static void print_explain(FILE *f)
27*de1e4e89SAndroid Build Coastguard Worker {
28*de1e4e89SAndroid Build Coastguard Worker fprintf(f,
29*de1e4e89SAndroid Build Coastguard Worker "Usage: ... vxlan id VNI\n"
30*de1e4e89SAndroid Build Coastguard Worker " [ { group | remote } IP_ADDRESS ]\n"
31*de1e4e89SAndroid Build Coastguard Worker " [ local ADDR ]\n"
32*de1e4e89SAndroid Build Coastguard Worker " [ ttl TTL ]\n"
33*de1e4e89SAndroid Build Coastguard Worker " [ tos TOS ]\n"
34*de1e4e89SAndroid Build Coastguard Worker " [ flowlabel LABEL ]\n"
35*de1e4e89SAndroid Build Coastguard Worker " [ dev PHYS_DEV ]\n"
36*de1e4e89SAndroid Build Coastguard Worker " [ dstport PORT ]\n"
37*de1e4e89SAndroid Build Coastguard Worker " [ srcport MIN MAX ]\n"
38*de1e4e89SAndroid Build Coastguard Worker " [ [no]learning ]\n"
39*de1e4e89SAndroid Build Coastguard Worker " [ [no]proxy ]\n"
40*de1e4e89SAndroid Build Coastguard Worker " [ [no]rsc ]\n"
41*de1e4e89SAndroid Build Coastguard Worker " [ [no]l2miss ]\n"
42*de1e4e89SAndroid Build Coastguard Worker " [ [no]l3miss ]\n"
43*de1e4e89SAndroid Build Coastguard Worker " [ ageing SECONDS ]\n"
44*de1e4e89SAndroid Build Coastguard Worker " [ maxaddress NUMBER ]\n"
45*de1e4e89SAndroid Build Coastguard Worker " [ [no]udpcsum ]\n"
46*de1e4e89SAndroid Build Coastguard Worker " [ [no]udp6zerocsumtx ]\n"
47*de1e4e89SAndroid Build Coastguard Worker " [ [no]udp6zerocsumrx ]\n"
48*de1e4e89SAndroid Build Coastguard Worker " [ [no]remcsumtx ] [ [no]remcsumrx ]\n"
49*de1e4e89SAndroid Build Coastguard Worker " [ [no]external ] [ gbp ] [ gpe ]\n"
50*de1e4e89SAndroid Build Coastguard Worker "\n"
51*de1e4e89SAndroid Build Coastguard Worker "Where: VNI := 0-16777215\n"
52*de1e4e89SAndroid Build Coastguard Worker " ADDR := { IP_ADDRESS | any }\n"
53*de1e4e89SAndroid Build Coastguard Worker " TOS := { NUMBER | inherit }\n"
54*de1e4e89SAndroid Build Coastguard Worker " TTL := { 1..255 | inherit }\n"
55*de1e4e89SAndroid Build Coastguard Worker " LABEL := 0-1048575\n"
56*de1e4e89SAndroid Build Coastguard Worker );
57*de1e4e89SAndroid Build Coastguard Worker }
58*de1e4e89SAndroid Build Coastguard Worker
explain(void)59*de1e4e89SAndroid Build Coastguard Worker static void explain(void)
60*de1e4e89SAndroid Build Coastguard Worker {
61*de1e4e89SAndroid Build Coastguard Worker print_explain(stderr);
62*de1e4e89SAndroid Build Coastguard Worker }
63*de1e4e89SAndroid Build Coastguard Worker
check_duparg(__u64 * attrs,int type,const char * key,const char * argv)64*de1e4e89SAndroid Build Coastguard Worker static void check_duparg(__u64 *attrs, int type, const char *key,
65*de1e4e89SAndroid Build Coastguard Worker const char *argv)
66*de1e4e89SAndroid Build Coastguard Worker {
67*de1e4e89SAndroid Build Coastguard Worker if (!VXLAN_ATTRSET(*attrs, type)) {
68*de1e4e89SAndroid Build Coastguard Worker *attrs |= (1L << type);
69*de1e4e89SAndroid Build Coastguard Worker return;
70*de1e4e89SAndroid Build Coastguard Worker }
71*de1e4e89SAndroid Build Coastguard Worker duparg2(key, argv);
72*de1e4e89SAndroid Build Coastguard Worker }
73*de1e4e89SAndroid Build Coastguard Worker
vxlan_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * n)74*de1e4e89SAndroid Build Coastguard Worker static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
75*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *n)
76*de1e4e89SAndroid Build Coastguard Worker {
77*de1e4e89SAndroid Build Coastguard Worker __u32 vni = 0;
78*de1e4e89SAndroid Build Coastguard Worker __u32 gaddr = 0;
79*de1e4e89SAndroid Build Coastguard Worker __u32 daddr = 0;
80*de1e4e89SAndroid Build Coastguard Worker struct in6_addr gaddr6 = IN6ADDR_ANY_INIT;
81*de1e4e89SAndroid Build Coastguard Worker struct in6_addr daddr6 = IN6ADDR_ANY_INIT;
82*de1e4e89SAndroid Build Coastguard Worker __u8 learning = 1;
83*de1e4e89SAndroid Build Coastguard Worker __u16 dstport = 0;
84*de1e4e89SAndroid Build Coastguard Worker __u8 metadata = 0;
85*de1e4e89SAndroid Build Coastguard Worker __u64 attrs = 0;
86*de1e4e89SAndroid Build Coastguard Worker bool set_op = (n->nlmsg_type == RTM_NEWLINK &&
87*de1e4e89SAndroid Build Coastguard Worker !(n->nlmsg_flags & NLM_F_CREATE));
88*de1e4e89SAndroid Build Coastguard Worker
89*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
90*de1e4e89SAndroid Build Coastguard Worker if (!matches(*argv, "id") ||
91*de1e4e89SAndroid Build Coastguard Worker !matches(*argv, "vni")) {
92*de1e4e89SAndroid Build Coastguard Worker /* We will add ID attribute outside of the loop since we
93*de1e4e89SAndroid Build Coastguard Worker * need to consider metadata information as well.
94*de1e4e89SAndroid Build Coastguard Worker */
95*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
96*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_ID, "id", *argv);
97*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&vni, *argv, 0) ||
98*de1e4e89SAndroid Build Coastguard Worker vni >= 1u << 24)
99*de1e4e89SAndroid Build Coastguard Worker invarg("invalid id", *argv);
100*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "group")) {
101*de1e4e89SAndroid Build Coastguard Worker if (daddr || !IN6_IS_ADDR_UNSPECIFIED(&daddr6)) {
102*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "vxlan: both group and remote");
103*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " cannot be specified\n");
104*de1e4e89SAndroid Build Coastguard Worker return -1;
105*de1e4e89SAndroid Build Coastguard Worker }
106*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
107*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_GROUP, "group", *argv);
108*de1e4e89SAndroid Build Coastguard Worker if (!inet_get_addr(*argv, &gaddr, &gaddr6)) {
109*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Invalid address \"%s\"\n", *argv);
110*de1e4e89SAndroid Build Coastguard Worker return -1;
111*de1e4e89SAndroid Build Coastguard Worker }
112*de1e4e89SAndroid Build Coastguard Worker if (!IN6_IS_ADDR_MULTICAST(&gaddr6) && !IN_MULTICAST(ntohl(gaddr)))
113*de1e4e89SAndroid Build Coastguard Worker invarg("invalid group address", *argv);
114*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "remote")) {
115*de1e4e89SAndroid Build Coastguard Worker if (gaddr || !IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) {
116*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "vxlan: both group and remote");
117*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " cannot be specified\n");
118*de1e4e89SAndroid Build Coastguard Worker return -1;
119*de1e4e89SAndroid Build Coastguard Worker }
120*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
121*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_GROUP, "remote", *argv);
122*de1e4e89SAndroid Build Coastguard Worker if (!inet_get_addr(*argv, &daddr, &daddr6)) {
123*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Invalid address \"%s\"\n", *argv);
124*de1e4e89SAndroid Build Coastguard Worker return -1;
125*de1e4e89SAndroid Build Coastguard Worker }
126*de1e4e89SAndroid Build Coastguard Worker if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr)))
127*de1e4e89SAndroid Build Coastguard Worker invarg("invalid remote address", *argv);
128*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "local")) {
129*de1e4e89SAndroid Build Coastguard Worker __u32 saddr = 0;
130*de1e4e89SAndroid Build Coastguard Worker struct in6_addr saddr6 = IN6ADDR_ANY_INIT;
131*de1e4e89SAndroid Build Coastguard Worker
132*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
133*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_LOCAL, "local", *argv);
134*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "any")) {
135*de1e4e89SAndroid Build Coastguard Worker if (!inet_get_addr(*argv, &saddr, &saddr6)) {
136*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Invalid address \"%s\"\n", *argv);
137*de1e4e89SAndroid Build Coastguard Worker return -1;
138*de1e4e89SAndroid Build Coastguard Worker }
139*de1e4e89SAndroid Build Coastguard Worker }
140*de1e4e89SAndroid Build Coastguard Worker
141*de1e4e89SAndroid Build Coastguard Worker if (IN_MULTICAST(ntohl(saddr)) || IN6_IS_ADDR_MULTICAST(&saddr6))
142*de1e4e89SAndroid Build Coastguard Worker invarg("invalid local address", *argv);
143*de1e4e89SAndroid Build Coastguard Worker
144*de1e4e89SAndroid Build Coastguard Worker if (saddr)
145*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_LOCAL, &saddr, 4);
146*de1e4e89SAndroid Build Coastguard Worker else if (!IN6_IS_ADDR_UNSPECIFIED(&saddr6))
147*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_LOCAL6, &saddr6,
148*de1e4e89SAndroid Build Coastguard Worker sizeof(struct in6_addr));
149*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "dev")) {
150*de1e4e89SAndroid Build Coastguard Worker unsigned int link;
151*de1e4e89SAndroid Build Coastguard Worker
152*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
153*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_LINK, "dev", *argv);
154*de1e4e89SAndroid Build Coastguard Worker link = if_nametoindex(*argv);
155*de1e4e89SAndroid Build Coastguard Worker if (link == 0) {
156*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Cannot find device \"%s\"\n",
157*de1e4e89SAndroid Build Coastguard Worker *argv);
158*de1e4e89SAndroid Build Coastguard Worker exit(-1);
159*de1e4e89SAndroid Build Coastguard Worker }
160*de1e4e89SAndroid Build Coastguard Worker addattr32(n, 1024, IFLA_VXLAN_LINK, link);
161*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "ttl") ||
162*de1e4e89SAndroid Build Coastguard Worker !matches(*argv, "hoplimit")) {
163*de1e4e89SAndroid Build Coastguard Worker unsigned int uval;
164*de1e4e89SAndroid Build Coastguard Worker __u8 ttl = 0;
165*de1e4e89SAndroid Build Coastguard Worker
166*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
167*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_TTL, "ttl", *argv);
168*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "inherit") != 0) {
169*de1e4e89SAndroid Build Coastguard Worker if (get_unsigned(&uval, *argv, 0))
170*de1e4e89SAndroid Build Coastguard Worker invarg("invalid TTL", *argv);
171*de1e4e89SAndroid Build Coastguard Worker if (uval > 255)
172*de1e4e89SAndroid Build Coastguard Worker invarg("TTL must be <= 255", *argv);
173*de1e4e89SAndroid Build Coastguard Worker ttl = uval;
174*de1e4e89SAndroid Build Coastguard Worker }
175*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_TTL, ttl);
176*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "tos") ||
177*de1e4e89SAndroid Build Coastguard Worker !matches(*argv, "dsfield")) {
178*de1e4e89SAndroid Build Coastguard Worker __u32 uval;
179*de1e4e89SAndroid Build Coastguard Worker __u8 tos;
180*de1e4e89SAndroid Build Coastguard Worker
181*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
182*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_TOS, "tos", *argv);
183*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "inherit") != 0) {
184*de1e4e89SAndroid Build Coastguard Worker if (rtnl_dsfield_a2n(&uval, *argv))
185*de1e4e89SAndroid Build Coastguard Worker invarg("bad TOS value", *argv);
186*de1e4e89SAndroid Build Coastguard Worker tos = uval;
187*de1e4e89SAndroid Build Coastguard Worker } else
188*de1e4e89SAndroid Build Coastguard Worker tos = 1;
189*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_TOS, tos);
190*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "label") ||
191*de1e4e89SAndroid Build Coastguard Worker !matches(*argv, "flowlabel")) {
192*de1e4e89SAndroid Build Coastguard Worker __u32 uval;
193*de1e4e89SAndroid Build Coastguard Worker
194*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
195*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_LABEL, "flowlabel",
196*de1e4e89SAndroid Build Coastguard Worker *argv);
197*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&uval, *argv, 0) ||
198*de1e4e89SAndroid Build Coastguard Worker (uval & ~LABEL_MAX_MASK))
199*de1e4e89SAndroid Build Coastguard Worker invarg("invalid flowlabel", *argv);
200*de1e4e89SAndroid Build Coastguard Worker addattr32(n, 1024, IFLA_VXLAN_LABEL, htonl(uval));
201*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "ageing")) {
202*de1e4e89SAndroid Build Coastguard Worker __u32 age;
203*de1e4e89SAndroid Build Coastguard Worker
204*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
205*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_AGEING, "ageing",
206*de1e4e89SAndroid Build Coastguard Worker *argv);
207*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "none") == 0)
208*de1e4e89SAndroid Build Coastguard Worker age = 0;
209*de1e4e89SAndroid Build Coastguard Worker else if (get_u32(&age, *argv, 0))
210*de1e4e89SAndroid Build Coastguard Worker invarg("ageing timer", *argv);
211*de1e4e89SAndroid Build Coastguard Worker addattr32(n, 1024, IFLA_VXLAN_AGEING, age);
212*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "maxaddress")) {
213*de1e4e89SAndroid Build Coastguard Worker __u32 maxaddr;
214*de1e4e89SAndroid Build Coastguard Worker
215*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
216*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_LIMIT,
217*de1e4e89SAndroid Build Coastguard Worker "maxaddress", *argv);
218*de1e4e89SAndroid Build Coastguard Worker if (strcmp(*argv, "unlimited") == 0)
219*de1e4e89SAndroid Build Coastguard Worker maxaddr = 0;
220*de1e4e89SAndroid Build Coastguard Worker else if (get_u32(&maxaddr, *argv, 0))
221*de1e4e89SAndroid Build Coastguard Worker invarg("max addresses", *argv);
222*de1e4e89SAndroid Build Coastguard Worker addattr32(n, 1024, IFLA_VXLAN_LIMIT, maxaddr);
223*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "port") ||
224*de1e4e89SAndroid Build Coastguard Worker !matches(*argv, "srcport")) {
225*de1e4e89SAndroid Build Coastguard Worker struct ifla_vxlan_port_range range = { 0, 0 };
226*de1e4e89SAndroid Build Coastguard Worker
227*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
228*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_PORT_RANGE, "srcport",
229*de1e4e89SAndroid Build Coastguard Worker *argv);
230*de1e4e89SAndroid Build Coastguard Worker if (get_be16(&range.low, *argv, 0))
231*de1e4e89SAndroid Build Coastguard Worker invarg("min port", *argv);
232*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
233*de1e4e89SAndroid Build Coastguard Worker if (get_be16(&range.high, *argv, 0))
234*de1e4e89SAndroid Build Coastguard Worker invarg("max port", *argv);
235*de1e4e89SAndroid Build Coastguard Worker if (range.low || range.high) {
236*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_PORT_RANGE,
237*de1e4e89SAndroid Build Coastguard Worker &range, sizeof(range));
238*de1e4e89SAndroid Build Coastguard Worker }
239*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "dstport")) {
240*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
241*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_PORT, "dstport", *argv);
242*de1e4e89SAndroid Build Coastguard Worker if (get_u16(&dstport, *argv, 0))
243*de1e4e89SAndroid Build Coastguard Worker invarg("dst port", *argv);
244*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "nolearning")) {
245*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_LEARNING, *argv, *argv);
246*de1e4e89SAndroid Build Coastguard Worker learning = 0;
247*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "learning")) {
248*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_LEARNING, *argv, *argv);
249*de1e4e89SAndroid Build Coastguard Worker learning = 1;
250*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "noproxy")) {
251*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_PROXY, *argv, *argv);
252*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_PROXY, 0);
253*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "proxy")) {
254*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_PROXY, *argv, *argv);
255*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_PROXY, 1);
256*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "norsc")) {
257*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_RSC, *argv, *argv);
258*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_RSC, 0);
259*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "rsc")) {
260*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_RSC, *argv, *argv);
261*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_RSC, 1);
262*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "nol2miss")) {
263*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_L2MISS, *argv, *argv);
264*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_L2MISS, 0);
265*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "l2miss")) {
266*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_L2MISS, *argv, *argv);
267*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_L2MISS, 1);
268*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "nol3miss")) {
269*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_L3MISS, *argv, *argv);
270*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_L3MISS, 0);
271*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "l3miss")) {
272*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_L3MISS, *argv, *argv);
273*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_L3MISS, 1);
274*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "udpcsum")) {
275*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_UDP_CSUM, *argv, *argv);
276*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_UDP_CSUM, 1);
277*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "noudpcsum")) {
278*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_UDP_CSUM, *argv, *argv);
279*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_UDP_CSUM, 0);
280*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "udp6zerocsumtx")) {
281*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
282*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
283*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, 1);
284*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "noudp6zerocsumtx")) {
285*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
286*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
287*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, 0);
288*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "udp6zerocsumrx")) {
289*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
290*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
291*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, 1);
292*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "noudp6zerocsumrx")) {
293*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
294*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
295*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, 0);
296*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "remcsumtx")) {
297*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_REMCSUM_TX,
298*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
299*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_REMCSUM_TX, 1);
300*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "noremcsumtx")) {
301*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_REMCSUM_TX,
302*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
303*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_REMCSUM_TX, 0);
304*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "remcsumrx")) {
305*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_REMCSUM_RX,
306*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
307*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_REMCSUM_RX, 1);
308*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "noremcsumrx")) {
309*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_REMCSUM_RX,
310*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
311*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_REMCSUM_RX, 0);
312*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "external")) {
313*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_COLLECT_METADATA,
314*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
315*de1e4e89SAndroid Build Coastguard Worker metadata = 1;
316*de1e4e89SAndroid Build Coastguard Worker learning = 0;
317*de1e4e89SAndroid Build Coastguard Worker /* we will add LEARNING attribute outside of the loop */
318*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_COLLECT_METADATA,
319*de1e4e89SAndroid Build Coastguard Worker metadata);
320*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "noexternal")) {
321*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_COLLECT_METADATA,
322*de1e4e89SAndroid Build Coastguard Worker *argv, *argv);
323*de1e4e89SAndroid Build Coastguard Worker metadata = 0;
324*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_COLLECT_METADATA,
325*de1e4e89SAndroid Build Coastguard Worker metadata);
326*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "gbp")) {
327*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_GBP, *argv, *argv);
328*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_GBP, NULL, 0);
329*de1e4e89SAndroid Build Coastguard Worker } else if (!matches(*argv, "gpe")) {
330*de1e4e89SAndroid Build Coastguard Worker check_duparg(&attrs, IFLA_VXLAN_GPE, *argv, *argv);
331*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_GPE, NULL, 0);
332*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "help") == 0) {
333*de1e4e89SAndroid Build Coastguard Worker explain();
334*de1e4e89SAndroid Build Coastguard Worker return -1;
335*de1e4e89SAndroid Build Coastguard Worker } else {
336*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "vxlan: unknown command \"%s\"?\n", *argv);
337*de1e4e89SAndroid Build Coastguard Worker explain();
338*de1e4e89SAndroid Build Coastguard Worker return -1;
339*de1e4e89SAndroid Build Coastguard Worker }
340*de1e4e89SAndroid Build Coastguard Worker argc--, argv++;
341*de1e4e89SAndroid Build Coastguard Worker }
342*de1e4e89SAndroid Build Coastguard Worker
343*de1e4e89SAndroid Build Coastguard Worker if (metadata && VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID)) {
344*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "vxlan: both 'external' and vni cannot be specified\n");
345*de1e4e89SAndroid Build Coastguard Worker return -1;
346*de1e4e89SAndroid Build Coastguard Worker }
347*de1e4e89SAndroid Build Coastguard Worker
348*de1e4e89SAndroid Build Coastguard Worker if (!metadata && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID)) {
349*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "vxlan: missing virtual network identifier\n");
350*de1e4e89SAndroid Build Coastguard Worker return -1;
351*de1e4e89SAndroid Build Coastguard Worker }
352*de1e4e89SAndroid Build Coastguard Worker
353*de1e4e89SAndroid Build Coastguard Worker if ((gaddr || !IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) &&
354*de1e4e89SAndroid Build Coastguard Worker !VXLAN_ATTRSET(attrs, IFLA_VXLAN_LINK)) {
355*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "vxlan: 'group' requires 'dev' to be specified\n");
356*de1e4e89SAndroid Build Coastguard Worker return -1;
357*de1e4e89SAndroid Build Coastguard Worker }
358*de1e4e89SAndroid Build Coastguard Worker
359*de1e4e89SAndroid Build Coastguard Worker if (!VXLAN_ATTRSET(attrs, IFLA_VXLAN_PORT) &&
360*de1e4e89SAndroid Build Coastguard Worker VXLAN_ATTRSET(attrs, IFLA_VXLAN_GPE)) {
361*de1e4e89SAndroid Build Coastguard Worker dstport = 4790;
362*de1e4e89SAndroid Build Coastguard Worker } else if (!VXLAN_ATTRSET(attrs, IFLA_VXLAN_PORT) && !set_op) {
363*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "vxlan: destination port not specified\n"
364*de1e4e89SAndroid Build Coastguard Worker "Will use Linux kernel default (non-standard value)\n");
365*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
366*de1e4e89SAndroid Build Coastguard Worker "Use 'dstport 4789' to get the IANA assigned value\n"
367*de1e4e89SAndroid Build Coastguard Worker "Use 'dstport 0' to get default and quiet this message\n");
368*de1e4e89SAndroid Build Coastguard Worker }
369*de1e4e89SAndroid Build Coastguard Worker
370*de1e4e89SAndroid Build Coastguard Worker addattr32(n, 1024, IFLA_VXLAN_ID, vni);
371*de1e4e89SAndroid Build Coastguard Worker if (gaddr)
372*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4);
373*de1e4e89SAndroid Build Coastguard Worker else if (daddr)
374*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4);
375*de1e4e89SAndroid Build Coastguard Worker else if (!IN6_IS_ADDR_UNSPECIFIED(&gaddr6))
376*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &gaddr6, sizeof(struct in6_addr));
377*de1e4e89SAndroid Build Coastguard Worker else if (!IN6_IS_ADDR_UNSPECIFIED(&daddr6))
378*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr));
379*de1e4e89SAndroid Build Coastguard Worker else if (preferred_family == AF_INET)
380*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4);
381*de1e4e89SAndroid Build Coastguard Worker else if (preferred_family == AF_INET6)
382*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr));
383*de1e4e89SAndroid Build Coastguard Worker
384*de1e4e89SAndroid Build Coastguard Worker if (!set_op || VXLAN_ATTRSET(attrs, IFLA_VXLAN_LEARNING))
385*de1e4e89SAndroid Build Coastguard Worker addattr8(n, 1024, IFLA_VXLAN_LEARNING, learning);
386*de1e4e89SAndroid Build Coastguard Worker
387*de1e4e89SAndroid Build Coastguard Worker if (dstport)
388*de1e4e89SAndroid Build Coastguard Worker addattr16(n, 1024, IFLA_VXLAN_PORT, htons(dstport));
389*de1e4e89SAndroid Build Coastguard Worker
390*de1e4e89SAndroid Build Coastguard Worker return 0;
391*de1e4e89SAndroid Build Coastguard Worker }
392*de1e4e89SAndroid Build Coastguard Worker
vxlan_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])393*de1e4e89SAndroid Build Coastguard Worker static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
394*de1e4e89SAndroid Build Coastguard Worker {
395*de1e4e89SAndroid Build Coastguard Worker __u32 vni;
396*de1e4e89SAndroid Build Coastguard Worker unsigned int link;
397*de1e4e89SAndroid Build Coastguard Worker __u8 tos;
398*de1e4e89SAndroid Build Coastguard Worker __u32 maxaddr;
399*de1e4e89SAndroid Build Coastguard Worker char s2[64];
400*de1e4e89SAndroid Build Coastguard Worker
401*de1e4e89SAndroid Build Coastguard Worker if (!tb)
402*de1e4e89SAndroid Build Coastguard Worker return;
403*de1e4e89SAndroid Build Coastguard Worker
404*de1e4e89SAndroid Build Coastguard Worker if (!tb[IFLA_VXLAN_ID] ||
405*de1e4e89SAndroid Build Coastguard Worker RTA_PAYLOAD(tb[IFLA_VXLAN_ID]) < sizeof(__u32))
406*de1e4e89SAndroid Build Coastguard Worker return;
407*de1e4e89SAndroid Build Coastguard Worker
408*de1e4e89SAndroid Build Coastguard Worker vni = rta_getattr_u32(tb[IFLA_VXLAN_ID]);
409*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_ANY, "id", "id %u ", vni);
410*de1e4e89SAndroid Build Coastguard Worker
411*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_GROUP]) {
412*de1e4e89SAndroid Build Coastguard Worker __be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_GROUP]);
413*de1e4e89SAndroid Build Coastguard Worker
414*de1e4e89SAndroid Build Coastguard Worker if (addr) {
415*de1e4e89SAndroid Build Coastguard Worker if (IN_MULTICAST(ntohl(addr)))
416*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_ANY,
417*de1e4e89SAndroid Build Coastguard Worker "group",
418*de1e4e89SAndroid Build Coastguard Worker "group %s ",
419*de1e4e89SAndroid Build Coastguard Worker format_host(AF_INET, 4, &addr));
420*de1e4e89SAndroid Build Coastguard Worker else
421*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_ANY,
422*de1e4e89SAndroid Build Coastguard Worker "remote",
423*de1e4e89SAndroid Build Coastguard Worker "remote %s ",
424*de1e4e89SAndroid Build Coastguard Worker format_host(AF_INET, 4, &addr));
425*de1e4e89SAndroid Build Coastguard Worker }
426*de1e4e89SAndroid Build Coastguard Worker } else if (tb[IFLA_VXLAN_GROUP6]) {
427*de1e4e89SAndroid Build Coastguard Worker struct in6_addr addr;
428*de1e4e89SAndroid Build Coastguard Worker
429*de1e4e89SAndroid Build Coastguard Worker memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_GROUP6]), sizeof(struct in6_addr));
430*de1e4e89SAndroid Build Coastguard Worker if (!IN6_IS_ADDR_UNSPECIFIED(&addr)) {
431*de1e4e89SAndroid Build Coastguard Worker if (IN6_IS_ADDR_MULTICAST(&addr))
432*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_ANY,
433*de1e4e89SAndroid Build Coastguard Worker "group6",
434*de1e4e89SAndroid Build Coastguard Worker "group %s ",
435*de1e4e89SAndroid Build Coastguard Worker format_host(AF_INET6,
436*de1e4e89SAndroid Build Coastguard Worker sizeof(struct in6_addr),
437*de1e4e89SAndroid Build Coastguard Worker &addr));
438*de1e4e89SAndroid Build Coastguard Worker else
439*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_ANY,
440*de1e4e89SAndroid Build Coastguard Worker "remote6",
441*de1e4e89SAndroid Build Coastguard Worker "remote %s ",
442*de1e4e89SAndroid Build Coastguard Worker format_host(AF_INET6,
443*de1e4e89SAndroid Build Coastguard Worker sizeof(struct in6_addr),
444*de1e4e89SAndroid Build Coastguard Worker &addr));
445*de1e4e89SAndroid Build Coastguard Worker }
446*de1e4e89SAndroid Build Coastguard Worker }
447*de1e4e89SAndroid Build Coastguard Worker
448*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_LOCAL]) {
449*de1e4e89SAndroid Build Coastguard Worker __be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_LOCAL]);
450*de1e4e89SAndroid Build Coastguard Worker
451*de1e4e89SAndroid Build Coastguard Worker if (addr)
452*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_ANY,
453*de1e4e89SAndroid Build Coastguard Worker "local",
454*de1e4e89SAndroid Build Coastguard Worker "local %s ",
455*de1e4e89SAndroid Build Coastguard Worker format_host(AF_INET, 4, &addr));
456*de1e4e89SAndroid Build Coastguard Worker } else if (tb[IFLA_VXLAN_LOCAL6]) {
457*de1e4e89SAndroid Build Coastguard Worker struct in6_addr addr;
458*de1e4e89SAndroid Build Coastguard Worker
459*de1e4e89SAndroid Build Coastguard Worker memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_LOCAL6]), sizeof(struct in6_addr));
460*de1e4e89SAndroid Build Coastguard Worker if (!IN6_IS_ADDR_UNSPECIFIED(&addr))
461*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_ANY,
462*de1e4e89SAndroid Build Coastguard Worker "local6",
463*de1e4e89SAndroid Build Coastguard Worker "local %s ",
464*de1e4e89SAndroid Build Coastguard Worker format_host(AF_INET6,
465*de1e4e89SAndroid Build Coastguard Worker sizeof(struct in6_addr),
466*de1e4e89SAndroid Build Coastguard Worker &addr));
467*de1e4e89SAndroid Build Coastguard Worker }
468*de1e4e89SAndroid Build Coastguard Worker
469*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_LINK] &&
470*de1e4e89SAndroid Build Coastguard Worker (link = rta_getattr_u32(tb[IFLA_VXLAN_LINK]))) {
471*de1e4e89SAndroid Build Coastguard Worker const char *n = if_indextoname(link, s2);
472*de1e4e89SAndroid Build Coastguard Worker
473*de1e4e89SAndroid Build Coastguard Worker if (n)
474*de1e4e89SAndroid Build Coastguard Worker print_string(PRINT_ANY, "link", "dev %s ", n);
475*de1e4e89SAndroid Build Coastguard Worker else
476*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_ANY, "link_index", "dev %u ", link);
477*de1e4e89SAndroid Build Coastguard Worker }
478*de1e4e89SAndroid Build Coastguard Worker
479*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_PORT_RANGE]) {
480*de1e4e89SAndroid Build Coastguard Worker const struct ifla_vxlan_port_range *r
481*de1e4e89SAndroid Build Coastguard Worker = RTA_DATA(tb[IFLA_VXLAN_PORT_RANGE]);
482*de1e4e89SAndroid Build Coastguard Worker if (is_json_context()) {
483*de1e4e89SAndroid Build Coastguard Worker open_json_object("port_range");
484*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_JSON, "low", NULL, ntohs(r->low));
485*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_JSON, "high", NULL, ntohs(r->high));
486*de1e4e89SAndroid Build Coastguard Worker close_json_object();
487*de1e4e89SAndroid Build Coastguard Worker } else {
488*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "srcport %u %u ",
489*de1e4e89SAndroid Build Coastguard Worker ntohs(r->low), ntohs(r->high));
490*de1e4e89SAndroid Build Coastguard Worker }
491*de1e4e89SAndroid Build Coastguard Worker }
492*de1e4e89SAndroid Build Coastguard Worker
493*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_PORT])
494*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_ANY,
495*de1e4e89SAndroid Build Coastguard Worker "port",
496*de1e4e89SAndroid Build Coastguard Worker "dstport %u ",
497*de1e4e89SAndroid Build Coastguard Worker rta_getattr_be16(tb[IFLA_VXLAN_PORT]));
498*de1e4e89SAndroid Build Coastguard Worker
499*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_LEARNING]) {
500*de1e4e89SAndroid Build Coastguard Worker __u8 learning = rta_getattr_u8(tb[IFLA_VXLAN_LEARNING]);
501*de1e4e89SAndroid Build Coastguard Worker
502*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_JSON, "learning", NULL, learning);
503*de1e4e89SAndroid Build Coastguard Worker if (!learning)
504*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_FP, NULL, "nolearning ", true);
505*de1e4e89SAndroid Build Coastguard Worker }
506*de1e4e89SAndroid Build Coastguard Worker
507*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_PROXY] && rta_getattr_u8(tb[IFLA_VXLAN_PROXY]))
508*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "proxy", "proxy ", true);
509*de1e4e89SAndroid Build Coastguard Worker
510*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_RSC] && rta_getattr_u8(tb[IFLA_VXLAN_RSC]))
511*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "rsc", "rsc ", true);
512*de1e4e89SAndroid Build Coastguard Worker
513*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_L2MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L2MISS]))
514*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "l2miss", "l2miss ", true);
515*de1e4e89SAndroid Build Coastguard Worker
516*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_L3MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L3MISS]))
517*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "l3miss", "l3miss ", true);
518*de1e4e89SAndroid Build Coastguard Worker
519*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_TOS] &&
520*de1e4e89SAndroid Build Coastguard Worker (tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]))) {
521*de1e4e89SAndroid Build Coastguard Worker if (is_json_context()) {
522*de1e4e89SAndroid Build Coastguard Worker print_0xhex(PRINT_JSON, "tos", "%#x", tos);
523*de1e4e89SAndroid Build Coastguard Worker } else {
524*de1e4e89SAndroid Build Coastguard Worker if (tos == 1)
525*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "tos %s ", "inherit");
526*de1e4e89SAndroid Build Coastguard Worker else
527*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "tos %#x ", tos);
528*de1e4e89SAndroid Build Coastguard Worker }
529*de1e4e89SAndroid Build Coastguard Worker }
530*de1e4e89SAndroid Build Coastguard Worker
531*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_TTL]) {
532*de1e4e89SAndroid Build Coastguard Worker __u8 ttl = rta_getattr_u8(tb[IFLA_VXLAN_TTL]);
533*de1e4e89SAndroid Build Coastguard Worker
534*de1e4e89SAndroid Build Coastguard Worker if (ttl)
535*de1e4e89SAndroid Build Coastguard Worker print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
536*de1e4e89SAndroid Build Coastguard Worker else
537*de1e4e89SAndroid Build Coastguard Worker print_int(PRINT_JSON, "ttl", NULL, ttl);
538*de1e4e89SAndroid Build Coastguard Worker }
539*de1e4e89SAndroid Build Coastguard Worker
540*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_LABEL]) {
541*de1e4e89SAndroid Build Coastguard Worker __u32 label = rta_getattr_u32(tb[IFLA_VXLAN_LABEL]);
542*de1e4e89SAndroid Build Coastguard Worker
543*de1e4e89SAndroid Build Coastguard Worker if (label)
544*de1e4e89SAndroid Build Coastguard Worker print_0xhex(PRINT_ANY,
545*de1e4e89SAndroid Build Coastguard Worker "label",
546*de1e4e89SAndroid Build Coastguard Worker "flowlabel %#x ",
547*de1e4e89SAndroid Build Coastguard Worker ntohl(label));
548*de1e4e89SAndroid Build Coastguard Worker }
549*de1e4e89SAndroid Build Coastguard Worker
550*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_AGEING]) {
551*de1e4e89SAndroid Build Coastguard Worker __u32 age = rta_getattr_u32(tb[IFLA_VXLAN_AGEING]);
552*de1e4e89SAndroid Build Coastguard Worker
553*de1e4e89SAndroid Build Coastguard Worker if (age == 0)
554*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_ANY, "ageing", "ageing none ", 0);
555*de1e4e89SAndroid Build Coastguard Worker else
556*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_ANY, "ageing", "ageing %u ", age);
557*de1e4e89SAndroid Build Coastguard Worker }
558*de1e4e89SAndroid Build Coastguard Worker
559*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_LIMIT] &&
560*de1e4e89SAndroid Build Coastguard Worker ((maxaddr = rta_getattr_u32(tb[IFLA_VXLAN_LIMIT])) != 0))
561*de1e4e89SAndroid Build Coastguard Worker print_uint(PRINT_ANY, "limit", "maxaddr %u ", maxaddr);
562*de1e4e89SAndroid Build Coastguard Worker
563*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_UDP_CSUM]) {
564*de1e4e89SAndroid Build Coastguard Worker __u8 udp_csum = rta_getattr_u8(tb[IFLA_VXLAN_UDP_CSUM]);
565*de1e4e89SAndroid Build Coastguard Worker
566*de1e4e89SAndroid Build Coastguard Worker if (is_json_context()) {
567*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "udp_csum", NULL, udp_csum);
568*de1e4e89SAndroid Build Coastguard Worker } else {
569*de1e4e89SAndroid Build Coastguard Worker if (!udp_csum)
570*de1e4e89SAndroid Build Coastguard Worker fputs("no", f);
571*de1e4e89SAndroid Build Coastguard Worker fputs("udpcsum ", f);
572*de1e4e89SAndroid Build Coastguard Worker }
573*de1e4e89SAndroid Build Coastguard Worker }
574*de1e4e89SAndroid Build Coastguard Worker
575*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) {
576*de1e4e89SAndroid Build Coastguard Worker __u8 csum6 = rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]);
577*de1e4e89SAndroid Build Coastguard Worker
578*de1e4e89SAndroid Build Coastguard Worker if (is_json_context()) {
579*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY,
580*de1e4e89SAndroid Build Coastguard Worker "udp_zero_csum6_tx", NULL, csum6);
581*de1e4e89SAndroid Build Coastguard Worker } else {
582*de1e4e89SAndroid Build Coastguard Worker if (!csum6)
583*de1e4e89SAndroid Build Coastguard Worker fputs("no", f);
584*de1e4e89SAndroid Build Coastguard Worker fputs("udp6zerocsumtx ", f);
585*de1e4e89SAndroid Build Coastguard Worker }
586*de1e4e89SAndroid Build Coastguard Worker }
587*de1e4e89SAndroid Build Coastguard Worker
588*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]) {
589*de1e4e89SAndroid Build Coastguard Worker __u8 csum6 = rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]);
590*de1e4e89SAndroid Build Coastguard Worker
591*de1e4e89SAndroid Build Coastguard Worker if (is_json_context()) {
592*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY,
593*de1e4e89SAndroid Build Coastguard Worker "udp_zero_csum6_rx",
594*de1e4e89SAndroid Build Coastguard Worker NULL,
595*de1e4e89SAndroid Build Coastguard Worker csum6);
596*de1e4e89SAndroid Build Coastguard Worker } else {
597*de1e4e89SAndroid Build Coastguard Worker if (!csum6)
598*de1e4e89SAndroid Build Coastguard Worker fputs("no", f);
599*de1e4e89SAndroid Build Coastguard Worker fputs("udp6zerocsumrx ", f);
600*de1e4e89SAndroid Build Coastguard Worker }
601*de1e4e89SAndroid Build Coastguard Worker }
602*de1e4e89SAndroid Build Coastguard Worker
603*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_REMCSUM_TX] &&
604*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(tb[IFLA_VXLAN_REMCSUM_TX]))
605*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "remcsum_tx", "remcsumtx ", true);
606*de1e4e89SAndroid Build Coastguard Worker
607*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_REMCSUM_RX] &&
608*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(tb[IFLA_VXLAN_REMCSUM_RX]))
609*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "remcsum_rx", "remcsumrx ", true);
610*de1e4e89SAndroid Build Coastguard Worker
611*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_COLLECT_METADATA] &&
612*de1e4e89SAndroid Build Coastguard Worker rta_getattr_u8(tb[IFLA_VXLAN_COLLECT_METADATA]))
613*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "collect_metadata", "external ", true);
614*de1e4e89SAndroid Build Coastguard Worker
615*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_GBP])
616*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "gbp", "gbp ", true);
617*de1e4e89SAndroid Build Coastguard Worker if (tb[IFLA_VXLAN_GPE])
618*de1e4e89SAndroid Build Coastguard Worker print_bool(PRINT_ANY, "gpe", "gpe ", true);
619*de1e4e89SAndroid Build Coastguard Worker }
620*de1e4e89SAndroid Build Coastguard Worker
vxlan_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)621*de1e4e89SAndroid Build Coastguard Worker static void vxlan_print_help(struct link_util *lu, int argc, char **argv,
622*de1e4e89SAndroid Build Coastguard Worker FILE *f)
623*de1e4e89SAndroid Build Coastguard Worker {
624*de1e4e89SAndroid Build Coastguard Worker print_explain(f);
625*de1e4e89SAndroid Build Coastguard Worker }
626*de1e4e89SAndroid Build Coastguard Worker
627*de1e4e89SAndroid Build Coastguard Worker struct link_util vxlan_link_util = {
628*de1e4e89SAndroid Build Coastguard Worker .id = "vxlan",
629*de1e4e89SAndroid Build Coastguard Worker .maxattr = IFLA_VXLAN_MAX,
630*de1e4e89SAndroid Build Coastguard Worker .parse_opt = vxlan_parse_opt,
631*de1e4e89SAndroid Build Coastguard Worker .print_opt = vxlan_print_opt,
632*de1e4e89SAndroid Build Coastguard Worker .print_help = vxlan_print_help,
633*de1e4e89SAndroid Build Coastguard Worker };
634