aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Stevens <dlstevens@us.ibm.com>2012-11-19 21:50:14 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-20 13:41:28 -0500
commite4f67addf158f98f8197e08974966b18480dc751 (patch)
tree01f1a199c7d875c89d3b8f4345ec3d0f03d0cbe7
parentff33c0e1885cda44dd14c79f70df4706f83582a0 (diff)
add DOVE extensions for VXLAN
This patch provides extensions to VXLAN for supporting Distributed Overlay Virtual Ethernet (DOVE) networks. The patch includes: + a dove flag per VXLAN device to enable DOVE extensions + ARP reduction, whereby a bridge-connected VXLAN tunnel endpoint answers ARP requests from the local bridge on behalf of remote DOVE clients + route short-circuiting (aka L3 switching). Known destination IP addresses use the corresponding destination MAC address for switching rather than going to a (possibly remote) router first. + netlink notification messages for forwarding table and L3 switching misses Changes since v2 - combined bools into "u32 flags" - replaced loop with !is_zero_ether_addr() Signed-off-by: David L Stevens <dlstevens@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/vxlan.c256
-rw-r--r--include/uapi/linux/if_link.h4
2 files changed, 235 insertions, 25 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index a14df1ce99ff..ce77b8b693ae 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -29,6 +29,8 @@
29#include <linux/etherdevice.h> 29#include <linux/etherdevice.h>
30#include <linux/if_ether.h> 30#include <linux/if_ether.h>
31#include <linux/hash.h> 31#include <linux/hash.h>
32#include <net/arp.h>
33#include <net/ndisc.h>
32#include <net/ip.h> 34#include <net/ip.h>
33#include <net/icmp.h> 35#include <net/icmp.h>
34#include <net/udp.h> 36#include <net/udp.h>
@@ -110,7 +112,7 @@ struct vxlan_dev {
110 __u16 port_max; 112 __u16 port_max;
111 __u8 tos; /* TOS override */ 113 __u8 tos; /* TOS override */
112 __u8 ttl; 114 __u8 ttl;
113 bool learn; 115 u32 flags; /* VXLAN_F_* below */
114 116
115 unsigned long age_interval; 117 unsigned long age_interval;
116 struct timer_list age_timer; 118 struct timer_list age_timer;
@@ -121,6 +123,12 @@ struct vxlan_dev {
121 struct hlist_head fdb_head[FDB_HASH_SIZE]; 123 struct hlist_head fdb_head[FDB_HASH_SIZE];
122}; 124};
123 125
126#define VXLAN_F_LEARN 0x01
127#define VXLAN_F_PROXY 0x02
128#define VXLAN_F_RSC 0x04
129#define VXLAN_F_L2MISS 0x08
130#define VXLAN_F_L3MISS 0x10
131
124/* salt for hash table */ 132/* salt for hash table */
125static u32 vxlan_salt __read_mostly; 133static u32 vxlan_salt __read_mostly;
126 134
@@ -154,6 +162,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
154 struct nda_cacheinfo ci; 162 struct nda_cacheinfo ci;
155 struct nlmsghdr *nlh; 163 struct nlmsghdr *nlh;
156 struct ndmsg *ndm; 164 struct ndmsg *ndm;
165 bool send_ip, send_eth;
157 166
158 nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags); 167 nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
159 if (nlh == NULL) 168 if (nlh == NULL)
@@ -161,16 +170,24 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
161 170
162 ndm = nlmsg_data(nlh); 171 ndm = nlmsg_data(nlh);
163 memset(ndm, 0, sizeof(*ndm)); 172 memset(ndm, 0, sizeof(*ndm));
164 ndm->ndm_family = AF_BRIDGE; 173
174 send_eth = send_ip = true;
175
176 if (type == RTM_GETNEIGH) {
177 ndm->ndm_family = AF_INET;
178 send_ip = fdb->remote_ip != 0;
179 send_eth = !is_zero_ether_addr(fdb->eth_addr);
180 } else
181 ndm->ndm_family = AF_BRIDGE;
165 ndm->ndm_state = fdb->state; 182 ndm->ndm_state = fdb->state;
166 ndm->ndm_ifindex = vxlan->dev->ifindex; 183 ndm->ndm_ifindex = vxlan->dev->ifindex;
167 ndm->ndm_flags = NTF_SELF; 184 ndm->ndm_flags = NTF_SELF;
168 ndm->ndm_type = NDA_DST; 185 ndm->ndm_type = NDA_DST;
169 186
170 if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr)) 187 if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
171 goto nla_put_failure; 188 goto nla_put_failure;
172 189
173 if (nla_put_be32(skb, NDA_DST, fdb->remote_ip)) 190 if (send_ip && nla_put_be32(skb, NDA_DST, fdb->remote_ip))
174 goto nla_put_failure; 191 goto nla_put_failure;
175 192
176 ci.ndm_used = jiffies_to_clock_t(now - fdb->used); 193 ci.ndm_used = jiffies_to_clock_t(now - fdb->used);
@@ -222,6 +239,29 @@ errout:
222 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); 239 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
223} 240}
224 241
242static void vxlan_ip_miss(struct net_device *dev, __be32 ipa)
243{
244 struct vxlan_dev *vxlan = netdev_priv(dev);
245 struct vxlan_fdb f;
246
247 memset(&f, 0, sizeof f);
248 f.state = NUD_STALE;
249 f.remote_ip = ipa; /* goes to NDA_DST */
250
251 vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
252}
253
254static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN])
255{
256 struct vxlan_fdb f;
257
258 memset(&f, 0, sizeof f);
259 f.state = NUD_STALE;
260 memcpy(f.eth_addr, eth_addr, ETH_ALEN);
261
262 vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
263}
264
225/* Hash Ethernet address */ 265/* Hash Ethernet address */
226static u32 eth_hash(const unsigned char *addr) 266static u32 eth_hash(const unsigned char *addr)
227{ 267{
@@ -551,6 +591,8 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
551 goto drop; 591 goto drop;
552 } 592 }
553 593
594 skb_reset_mac_header(skb);
595
554 /* Re-examine inner Ethernet packet */ 596 /* Re-examine inner Ethernet packet */
555 oip = ip_hdr(skb); 597 oip = ip_hdr(skb);
556 skb->protocol = eth_type_trans(skb, vxlan->dev); 598 skb->protocol = eth_type_trans(skb, vxlan->dev);
@@ -560,7 +602,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
560 vxlan->dev->dev_addr) == 0) 602 vxlan->dev->dev_addr) == 0)
561 goto drop; 603 goto drop;
562 604
563 if (vxlan->learn) 605 if (vxlan->flags & VXLAN_F_LEARN)
564 vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source); 606 vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source);
565 607
566 __skb_tunnel_rx(skb, vxlan->dev); 608 __skb_tunnel_rx(skb, vxlan->dev);
@@ -599,6 +641,117 @@ drop:
599 return 0; 641 return 0;
600} 642}
601 643
644static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
645{
646 struct vxlan_dev *vxlan = netdev_priv(dev);
647 struct arphdr *parp;
648 u8 *arpptr, *sha;
649 __be32 sip, tip;
650 struct neighbour *n;
651
652 if (dev->flags & IFF_NOARP)
653 goto out;
654
655 if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
656 dev->stats.tx_dropped++;
657 goto out;
658 }
659 parp = arp_hdr(skb);
660
661 if ((parp->ar_hrd != htons(ARPHRD_ETHER) &&
662 parp->ar_hrd != htons(ARPHRD_IEEE802)) ||
663 parp->ar_pro != htons(ETH_P_IP) ||
664 parp->ar_op != htons(ARPOP_REQUEST) ||
665 parp->ar_hln != dev->addr_len ||
666 parp->ar_pln != 4)
667 goto out;
668 arpptr = (u8 *)parp + sizeof(struct arphdr);
669 sha = arpptr;
670 arpptr += dev->addr_len; /* sha */
671 memcpy(&sip, arpptr, sizeof(sip));
672 arpptr += sizeof(sip);
673 arpptr += dev->addr_len; /* tha */
674 memcpy(&tip, arpptr, sizeof(tip));
675
676 if (ipv4_is_loopback(tip) ||
677 ipv4_is_multicast(tip))
678 goto out;
679
680 n = neigh_lookup(&arp_tbl, &tip, dev);
681
682 if (n) {
683 struct vxlan_dev *vxlan = netdev_priv(dev);
684 struct vxlan_fdb *f;
685 struct sk_buff *reply;
686
687 if (!(n->nud_state & NUD_CONNECTED)) {
688 neigh_release(n);
689 goto out;
690 }
691
692 f = vxlan_find_mac(vxlan, n->ha);
693 if (f && f->remote_ip == 0) {
694 /* bridge-local neighbor */
695 neigh_release(n);
696 goto out;
697 }
698
699 reply = arp_create(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
700 n->ha, sha);
701
702 neigh_release(n);
703
704 skb_reset_mac_header(reply);
705 __skb_pull(reply, skb_network_offset(reply));
706 reply->ip_summed = CHECKSUM_UNNECESSARY;
707 reply->pkt_type = PACKET_HOST;
708
709 if (netif_rx_ni(reply) == NET_RX_DROP)
710 dev->stats.rx_dropped++;
711 } else if (vxlan->flags & VXLAN_F_L3MISS)
712 vxlan_ip_miss(dev, tip);
713out:
714 consume_skb(skb);
715 return NETDEV_TX_OK;
716}
717
718static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
719{
720 struct vxlan_dev *vxlan = netdev_priv(dev);
721 struct neighbour *n;
722 struct iphdr *pip;
723
724 if (is_multicast_ether_addr(eth_hdr(skb)->h_dest))
725 return false;
726
727 n = NULL;
728 switch (ntohs(eth_hdr(skb)->h_proto)) {
729 case ETH_P_IP:
730 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
731 return false;
732 pip = ip_hdr(skb);
733 n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
734 break;
735 default:
736 return false;
737 }
738
739 if (n) {
740 bool diff;
741
742 diff = compare_ether_addr(eth_hdr(skb)->h_dest, n->ha) != 0;
743 if (diff) {
744 memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
745 dev->addr_len);
746 memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len);
747 }
748 neigh_release(n);
749 return diff;
750 } else if (vxlan->flags & VXLAN_F_L3MISS)
751 vxlan_ip_miss(dev, pip->daddr);
752 return false;
753}
754
602/* Extract dsfield from inner protocol */ 755/* Extract dsfield from inner protocol */
603static inline u8 vxlan_get_dsfield(const struct iphdr *iph, 756static inline u8 vxlan_get_dsfield(const struct iphdr *iph,
604 const struct sk_buff *skb) 757 const struct sk_buff *skb)
@@ -621,22 +774,6 @@ static inline u8 vxlan_ecn_encap(u8 tos,
621 return INET_ECN_encapsulate(tos, inner); 774 return INET_ECN_encapsulate(tos, inner);
622} 775}
623 776
624static __be32 vxlan_find_dst(struct vxlan_dev *vxlan, struct sk_buff *skb)
625{
626 const struct ethhdr *eth = (struct ethhdr *) skb->data;
627 const struct vxlan_fdb *f;
628
629 if (is_multicast_ether_addr(eth->h_dest))
630 return vxlan->gaddr;
631
632 f = vxlan_find_mac(vxlan, eth->h_dest);
633 if (f)
634 return f->remote_ip;
635 else
636 return vxlan->gaddr;
637
638}
639
640static void vxlan_sock_free(struct sk_buff *skb) 777static void vxlan_sock_free(struct sk_buff *skb)
641{ 778{
642 sock_put(skb->sk); 779 sock_put(skb->sk);
@@ -683,6 +820,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
683 struct vxlan_dev *vxlan = netdev_priv(dev); 820 struct vxlan_dev *vxlan = netdev_priv(dev);
684 struct rtable *rt; 821 struct rtable *rt;
685 const struct iphdr *old_iph; 822 const struct iphdr *old_iph;
823 struct ethhdr *eth;
686 struct iphdr *iph; 824 struct iphdr *iph;
687 struct vxlanhdr *vxh; 825 struct vxlanhdr *vxh;
688 struct udphdr *uh; 826 struct udphdr *uh;
@@ -693,10 +831,50 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
693 __be16 df = 0; 831 __be16 df = 0;
694 __u8 tos, ttl; 832 __u8 tos, ttl;
695 int err; 833 int err;
834 bool did_rsc = false;
835 const struct vxlan_fdb *f;
836
837 skb_reset_mac_header(skb);
838 eth = eth_hdr(skb);
839
840 if ((vxlan->flags & VXLAN_F_PROXY) && ntohs(eth->h_proto) == ETH_P_ARP)
841 return arp_reduce(dev, skb);
842 else if ((vxlan->flags&VXLAN_F_RSC) && ntohs(eth->h_proto) == ETH_P_IP)
843 did_rsc = route_shortcircuit(dev, skb);
696 844
697 dst = vxlan_find_dst(vxlan, skb); 845 f = vxlan_find_mac(vxlan, eth->h_dest);
698 if (!dst) 846 if (f == NULL) {
847 did_rsc = false;
848 dst = vxlan->gaddr;
849 if (!dst && (vxlan->flags & VXLAN_F_L2MISS) &&
850 !is_multicast_ether_addr(eth->h_dest))
851 vxlan_fdb_miss(vxlan, eth->h_dest);
852 } else
853 dst = f->remote_ip;
854
855 if (!dst) {
856 if (did_rsc) {
857 __skb_pull(skb, skb_network_offset(skb));
858 skb->ip_summed = CHECKSUM_NONE;
859 skb->pkt_type = PACKET_HOST;
860
861 /* short-circuited back to local bridge */
862 if (netif_rx(skb) == NET_RX_SUCCESS) {
863 struct vxlan_stats *stats =
864 this_cpu_ptr(vxlan->stats);
865
866 u64_stats_update_begin(&stats->syncp);
867 stats->tx_packets++;
868 stats->tx_bytes += pkt_len;
869 u64_stats_update_end(&stats->syncp);
870 } else {
871 dev->stats.tx_errors++;
872 dev->stats.tx_aborted_errors++;
873 }
874 return NETDEV_TX_OK;
875 }
699 goto drop; 876 goto drop;
877 }
700 878
701 /* Need space for new headers (invalidates iph ptr) */ 879 /* Need space for new headers (invalidates iph ptr) */
702 if (skb_cow_head(skb, VXLAN_HEADROOM)) 880 if (skb_cow_head(skb, VXLAN_HEADROOM))
@@ -1019,6 +1197,10 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
1019 [IFLA_VXLAN_AGEING] = { .type = NLA_U32 }, 1197 [IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
1020 [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 }, 1198 [IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
1021 [IFLA_VXLAN_PORT_RANGE] = { .len = sizeof(struct ifla_vxlan_port_range) }, 1199 [IFLA_VXLAN_PORT_RANGE] = { .len = sizeof(struct ifla_vxlan_port_range) },
1200 [IFLA_VXLAN_PROXY] = { .type = NLA_U8 },
1201 [IFLA_VXLAN_RSC] = { .type = NLA_U8 },
1202 [IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
1203 [IFLA_VXLAN_L3MISS] = { .type = NLA_U8 },
1022}; 1204};
1023 1205
1024static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) 1206static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1114,13 +1296,25 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
1114 vxlan->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]); 1296 vxlan->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]);
1115 1297
1116 if (!data[IFLA_VXLAN_LEARNING] || nla_get_u8(data[IFLA_VXLAN_LEARNING])) 1298 if (!data[IFLA_VXLAN_LEARNING] || nla_get_u8(data[IFLA_VXLAN_LEARNING]))
1117 vxlan->learn = true; 1299 vxlan->flags |= VXLAN_F_LEARN;
1118 1300
1119 if (data[IFLA_VXLAN_AGEING]) 1301 if (data[IFLA_VXLAN_AGEING])
1120 vxlan->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]); 1302 vxlan->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]);
1121 else 1303 else
1122 vxlan->age_interval = FDB_AGE_DEFAULT; 1304 vxlan->age_interval = FDB_AGE_DEFAULT;
1123 1305
1306 if (data[IFLA_VXLAN_PROXY] && nla_get_u8(data[IFLA_VXLAN_PROXY]))
1307 vxlan->flags |= VXLAN_F_PROXY;
1308
1309 if (data[IFLA_VXLAN_RSC] && nla_get_u8(data[IFLA_VXLAN_RSC]))
1310 vxlan->flags |= VXLAN_F_RSC;
1311
1312 if (data[IFLA_VXLAN_L2MISS] && nla_get_u8(data[IFLA_VXLAN_L2MISS]))
1313 vxlan->flags |= VXLAN_F_L2MISS;
1314
1315 if (data[IFLA_VXLAN_L3MISS] && nla_get_u8(data[IFLA_VXLAN_L3MISS]))
1316 vxlan->flags |= VXLAN_F_L3MISS;
1317
1124 if (data[IFLA_VXLAN_LIMIT]) 1318 if (data[IFLA_VXLAN_LIMIT])
1125 vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]); 1319 vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]);
1126 1320
@@ -1157,6 +1351,10 @@ static size_t vxlan_get_size(const struct net_device *dev)
1157 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */ 1351 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */
1158 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TOS */ 1352 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TOS */
1159 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */ 1353 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */
1354 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_PROXY */
1355 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_RSC */
1356 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_L2MISS */
1357 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_L3MISS */
1160 nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */ 1358 nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */
1161 nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */ 1359 nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */
1162 nla_total_size(sizeof(struct ifla_vxlan_port_range)) + 1360 nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
@@ -1185,7 +1383,15 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
1185 1383
1186 if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->ttl) || 1384 if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->ttl) ||
1187 nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->tos) || 1385 nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->tos) ||
1188 nla_put_u8(skb, IFLA_VXLAN_LEARNING, vxlan->learn) || 1386 nla_put_u8(skb, IFLA_VXLAN_LEARNING,
1387 !!(vxlan->flags & VXLAN_F_LEARN)) ||
1388 nla_put_u8(skb, IFLA_VXLAN_PROXY,
1389 !!(vxlan->flags & VXLAN_F_PROXY)) ||
1390 nla_put_u8(skb, IFLA_VXLAN_RSC, !!(vxlan->flags & VXLAN_F_RSC)) ||
1391 nla_put_u8(skb, IFLA_VXLAN_L2MISS,
1392 !!(vxlan->flags & VXLAN_F_L2MISS)) ||
1393 nla_put_u8(skb, IFLA_VXLAN_L3MISS,
1394 !!(vxlan->flags & VXLAN_F_L3MISS)) ||
1189 nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) || 1395 nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) ||
1190 nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax)) 1396 nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax))
1191 goto nla_put_failure; 1397 goto nla_put_failure;
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 7aae0179ae44..bb58aeb7f34d 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -302,6 +302,10 @@ enum {
302 IFLA_VXLAN_AGEING, 302 IFLA_VXLAN_AGEING,
303 IFLA_VXLAN_LIMIT, 303 IFLA_VXLAN_LIMIT,
304 IFLA_VXLAN_PORT_RANGE, 304 IFLA_VXLAN_PORT_RANGE,
305 IFLA_VXLAN_PROXY,
306 IFLA_VXLAN_RSC,
307 IFLA_VXLAN_L2MISS,
308 IFLA_VXLAN_L3MISS,
305 __IFLA_VXLAN_MAX 309 __IFLA_VXLAN_MAX
306}; 310};
307#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) 311#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)