2
* iplink_vxlan.c VXLAN device support
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version
7
* 2 of the License, or (at your option) any later version.
9
* Authors: Stephen Hemminger <shemminger@vyatta.com
17
#include <linux/if_link.h>
18
#include <arpa/inet.h>
22
#include "ip_common.h"
24
static void explain(void)
26
fprintf(stderr, "Usage: ... vxlan id VNI [ group ADDR ] [ local ADDR ]\n");
27
fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ dev PHYS_DEV ]\n");
28
fprintf(stderr, " [ port MIN MAX ] [ [no]learning ]\n");
29
fprintf(stderr, "\n");
30
fprintf(stderr, "Where: VNI := 0-16777215\n");
31
fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n");
32
fprintf(stderr, " TOS := { NUMBER | inherit }\n");
33
fprintf(stderr, " TTL := { 1..255 | inherit }\n");
36
static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
50
struct ifla_vxlan_port_range range = { 0, 0 };
53
if (!matches(*argv, "id") ||
54
!matches(*argv, "vni")) {
56
if (get_u32(&vni, *argv, 0) ||
58
invarg("invalid id", *argv);
60
} else if (!matches(*argv, "group")) {
62
gaddr = get_addr32(*argv);
64
if (!IN_MULTICAST(ntohl(gaddr)))
65
invarg("invald group address", *argv);
66
} else if (!matches(*argv, "local")) {
68
if (strcmp(*argv, "any"))
69
saddr = get_addr32(*argv);
70
if (IN_MULTICAST(ntohl(saddr)))
71
invarg("invalid local address", *argv);
72
} else if (!matches(*argv, "dev")) {
74
link = if_nametoindex(*argv);
77
} else if (!matches(*argv, "ttl") ||
78
!matches(*argv, "hoplimit")) {
82
if (strcmp(*argv, "inherit") != 0) {
83
if (get_unsigned(&uval, *argv, 0))
84
invarg("invalid TTL", *argv);
86
invarg("TTL must be <= 255", *argv);
89
} else if (!matches(*argv, "tos") ||
90
!matches(*argv, "dsfield")) {
94
if (strcmp(*argv, "inherit") != 0) {
95
if (rtnl_dsfield_a2n(&uval, *argv))
96
invarg("bad TOS value", *argv);
100
} else if (!matches(*argv, "ageing")) {
102
if (strcmp(*argv, "none") == 0)
104
else if (get_u32(&age, *argv, 0))
105
invarg("ageing timer", *argv);
106
} else if (!matches(*argv, "maxaddress")) {
108
if (strcmp(*argv, "unlimited") == 0)
110
else if (get_u32(&maxaddr, *argv, 0))
111
invarg("max addresses", *argv);
112
} else if (!matches(*argv, "port")) {
113
__u16 minport, maxport;
115
if (get_u16(&minport, *argv, 0))
116
invarg("min port", *argv);
118
if (get_u16(&maxport, *argv, 0))
119
invarg("max port", *argv);
120
range.low = htons(minport);
121
range.high = htons(maxport);
122
} else if (!matches(*argv, "nolearning")) {
124
} else if (!matches(*argv, "learning")) {
126
} else if (matches(*argv, "help") == 0) {
130
fprintf(stderr, "vxlan: what is \"%s\"?\n", *argv);
138
fprintf(stderr, "vxlan: missing virtual network identifier\n");
141
addattr32(n, 1024, IFLA_VXLAN_ID, vni);
143
addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4);
145
addattr_l(n, 1024, IFLA_VXLAN_LOCAL, &saddr, 4);
147
addattr32(n, 1024, IFLA_VXLAN_LINK, link);
148
addattr8(n, 1024, IFLA_VXLAN_TTL, ttl);
149
addattr8(n, 1024, IFLA_VXLAN_TOS, tos);
150
addattr8(n, 1024, IFLA_VXLAN_LEARNING, learning);
152
addattr32(n, 1024, IFLA_VXLAN_AGEING, 0);
154
addattr32(n, 1024, IFLA_VXLAN_AGEING, age);
156
addattr32(n, 1024, IFLA_VXLAN_LIMIT, maxaddr);
157
if (range.low || range.high)
158
addattr_l(n, 1024, IFLA_VXLAN_PORT_RANGE,
159
&range, sizeof(range));
164
static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
176
if (!tb[IFLA_VXLAN_ID] ||
177
RTA_PAYLOAD(tb[IFLA_VXLAN_ID]) < sizeof(__u32))
180
vni = rta_getattr_u32(tb[IFLA_VXLAN_ID]);
181
fprintf(f, "id %u ", vni);
183
if (tb[IFLA_VXLAN_GROUP]) {
184
__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_GROUP]);
186
fprintf(f, "group %s ",
187
format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
190
if (tb[IFLA_VXLAN_LOCAL]) {
191
__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_LOCAL]);
193
fprintf(f, "local %s ",
194
format_host(AF_INET, 4, &addr, s1, sizeof(s1)));
197
if (tb[IFLA_VXLAN_LINK] &&
198
(link = rta_getattr_u32(tb[IFLA_VXLAN_LINK]))) {
199
const char *n = if_indextoname(link, s2);
202
fprintf(f, "dev %s ", n);
204
fprintf(f, "dev %u ", link);
207
if (tb[IFLA_VXLAN_PORT_RANGE]) {
208
const struct ifla_vxlan_port_range *r
209
= RTA_DATA(tb[IFLA_VXLAN_PORT_RANGE]);
210
fprintf(f, "port %u %u ", ntohs(r->low), ntohs(r->high));
213
if (tb[IFLA_VXLAN_LEARNING] &&
214
!rta_getattr_u8(tb[IFLA_VXLAN_LEARNING]))
215
fputs("nolearning ", f);
217
if (tb[IFLA_VXLAN_TOS] &&
218
(tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]))) {
220
fprintf(f, "tos inherit ");
222
fprintf(f, "tos %#x ", tos);
225
if (tb[IFLA_VXLAN_TTL]) {
226
__u8 ttl = rta_getattr_u8(tb[IFLA_VXLAN_TTL]);
228
fprintf(f, "ttl %d ", ttl);
231
if (tb[IFLA_VXLAN_AGEING]) {
232
__u32 age = rta_getattr_u32(tb[IFLA_VXLAN_AGEING]);
234
fprintf(f, "ageing none ");
236
fprintf(f, "ageing %u ", age);
239
if (tb[IFLA_VXLAN_LIMIT] &&
240
(maxaddr = rta_getattr_u32(tb[IFLA_VXLAN_LIMIT]) != 0))
241
fprintf(f, "maxaddr %u ", maxaddr);
244
struct link_util vxlan_link_util = {
246
.maxattr = IFLA_VXLAN_MAX,
247
.parse_opt = vxlan_parse_opt,
248
.print_opt = vxlan_print_opt,