···
1
+
From e64058be3b97c5bd3e034fc4ece21e306ef6f90b Mon Sep 17 00:00:00 2001
2
+
From: Jay Vosburgh <jay.vosburgh@canonical.com>
3
+
Date: Wed, 1 Apr 2015 16:11:09 -0700
4
+
Subject: [PATCH] UBUNTU: SAUCE: fan: tunnel multiple mapping mode (v3)
6
+
Switch to a single tunnel for all mappings, this removes the limitations
7
+
on how many mappings each tunnel can handle, and therefore how many Fan
8
+
slices each local address may hold.
10
+
NOTE: This introduces a new kernel netlink interface which needs updated
13
+
BugLink: http://bugs.launchpad.net/bugs/1470091
14
+
Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
15
+
Signed-off-by: Andy Whitcroft <apw@canonical.com>
16
+
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
19
+
include/net/ip_tunnels.h
21
+
include/net/ip_tunnels.h | 15 ++++
22
+
include/uapi/linux/if_tunnel.h | 20 +++++
23
+
net/ipv4/ip_tunnel.c | 7 +-
24
+
net/ipv4/ipip.c | 186 +++++++++++++++++++++++++++++++++++++++--
25
+
4 files changed, 222 insertions(+), 6 deletions(-)
27
+
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
28
+
index 62a750a..47fec59 100644
29
+
--- a/include/net/ip_tunnels.h
30
+
+++ b/include/net/ip_tunnels.h
31
+
@@ -91,6 +91,19 @@ struct ip_tunnel_dst {
34
+
struct metadata_dst;
35
+
+/* A fan overlay /8 (250.0.0.0/8, for example) maps to exactly one /16
36
+
+ * underlay (10.88.0.0/16, for example). Multiple local addresses within
37
+
+ * the /16 may be used, but a particular overlay may not span
38
+
+ * multiple underlay subnets.
40
+
+ * We store one underlay, indexed by the overlay's high order octet.
42
+
+#define FAN_OVERLAY_CNT 256
44
+
+struct ip_tunnel_fan {
45
+
+/* u32 __rcu *map;*/
46
+
+ u32 map[FAN_OVERLAY_CNT];
50
+
struct ip_tunnel __rcu *next;
51
+
@@ -123,6 +136,7 @@ struct ip_tunnel {
53
+
struct ip_tunnel_prl_entry __rcu *prl; /* potential router list */
54
+
unsigned int prl_count; /* # of entries in PRL */
55
+
+ struct ip_tunnel_fan fan;
57
+
struct gro_cells gro_cells;
59
+
@@ -143,6 +157,7 @@ struct ip_tunnel {
60
+
#define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000)
62
+
#define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT)
63
+
+#define TUNNEL_FAN __cpu_to_be16(0x4000)
65
+
struct tnl_ptk_info {
67
+
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
68
+
index af4de90..85a3e4b 100644
69
+
--- a/include/uapi/linux/if_tunnel.h
70
+
+++ b/include/uapi/linux/if_tunnel.h
71
+
@@ -57,6 +57,10 @@ enum {
72
+
IFLA_IPTUN_ENCAP_FLAGS,
73
+
IFLA_IPTUN_ENCAP_SPORT,
74
+
IFLA_IPTUN_ENCAP_DPORT,
76
+
+ __IFLA_IPTUN_VENDOR_BREAK, /* Ensure new entries do not hit the below. */
77
+
+ IFLA_IPTUN_FAN_MAP = 33,
81
+
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
82
+
@@ -132,4 +136,20 @@ enum {
85
+
#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1)
93
+
+#define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
95
+
+struct ip_tunnel_fan_map {
98
+
+ __u16 underlay_prefix;
99
+
+ __u16 overlay_prefix;
102
+
#endif /* _UAPI_IF_TUNNEL_H_ */
103
+
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
104
+
index cbb51f3..7a6174b 100644
105
+
--- a/net/ipv4/ip_tunnel.c
106
+
+++ b/net/ipv4/ip_tunnel.c
107
+
@@ -1110,6 +1110,11 @@ out:
109
+
EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
111
+
+static int ip_tunnel_is_fan(struct ip_tunnel *tunnel)
113
+
+ return tunnel->parms.i_flags & TUNNEL_FAN;
116
+
int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
117
+
struct ip_tunnel_parm *p)
119
+
@@ -1119,7 +1124,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
120
+
struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
122
+
if (dev == itn->fb_tunnel_dev)
124
+
+ return ip_tunnel_is_fan(tunnel) ? 0 : -EINVAL;
126
+
t = ip_tunnel_find(itn, p, dev->type);
128
+
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
129
+
index a09fb0d..56e8984 100644
130
+
--- a/net/ipv4/ipip.c
131
+
+++ b/net/ipv4/ipip.c
132
+
@@ -107,6 +107,7 @@
133
+
#include <linux/init.h>
134
+
#include <linux/netfilter_ipv4.h>
135
+
#include <linux/if_ether.h>
136
+
+#include <linux/inetdevice.h>
138
+
#include <net/sock.h>
139
+
#include <net/ip.h>
140
+
@@ -208,6 +209,40 @@ drop:
144
+
+static int ipip_tunnel_is_fan(struct ip_tunnel *tunnel)
146
+
+ return tunnel->parms.i_flags & TUNNEL_FAN;
150
+
+ * Determine fan tunnel endpoint to send packet to, based on the inner IP
151
+
+ * address. For an overlay (inner) address Y.A.B.C, the transformation is
152
+
+ * F.G.A.B, where "F" and "G" are the first two octets of the underlay
153
+
+ * network (the network portion of a /16), "A" and "B" are the low order
154
+
+ * two octets of the underlay network host (the host portion of a /16),
155
+
+ * and "Y" is a configured first octet of the overlay network.
157
+
+ * E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
158
+
+ * subnet 99.3.4.0/24. An overlay network datagram from 99.3.4.5 to
159
+
+ * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
160
+
+ * overlay network 99.6.7.0/24.
162
+
+static int ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
164
+
+ unsigned int overlay;
165
+
+ u32 daddr, underlay;
167
+
+ daddr = ntohl(ip_hdr(skb)->daddr);
168
+
+ overlay = daddr >> 24;
169
+
+ underlay = tunnel->fan.map[overlay];
173
+
+ *iph = tunnel->parms.iph;
174
+
+ iph->daddr = htonl(underlay | ((daddr >> 8) & 0x0000ffff));
179
+
* This function assumes it is being called from dev_queue_xmit()
180
+
* and that skb is filled properly by that function.
181
+
@@ -215,7 +250,8 @@ drop:
182
+
static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
184
+
struct ip_tunnel *tunnel = netdev_priv(dev);
185
+
- const struct iphdr *tiph = &tunnel->parms.iph;
186
+
+ const struct iphdr *tiph;
187
+
+ struct iphdr fiph;
189
+
if (unlikely(skb->protocol != htons(ETH_P_IP)))
191
+
@@ -224,6 +260,14 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
195
+
+ if (ipip_tunnel_is_fan(tunnel)) {
196
+
+ if (ipip_build_fan_iphdr(tunnel, skb, &fiph))
200
+
+ tiph = &tunnel->parms.iph;
203
+
skb_set_inner_ipproto(skb, IPPROTO_IPIP);
205
+
ip_tunnel_xmit(skb, dev, tiph, tiph->protocol);
206
+
@@ -375,21 +419,88 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
210
+
+static void ipip_fan_free_map(struct ip_tunnel *t)
212
+
+ memset(&t->fan.map, 0, sizeof(t->fan.map));
215
+
+static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
217
+
+ u32 overlay, overlay_mask, underlay, underlay_mask;
219
+
+ if ((map->underlay_prefix && map->underlay_prefix != 16) ||
220
+
+ (map->overlay_prefix && map->overlay_prefix != 8))
223
+
+ overlay = ntohl(map->overlay);
224
+
+ overlay_mask = ntohl(inet_make_mask(map->overlay_prefix));
226
+
+ underlay = ntohl(map->underlay);
227
+
+ underlay_mask = ntohl(inet_make_mask(map->underlay_prefix));
229
+
+ if ((overlay & ~overlay_mask) || (underlay & ~underlay_mask))
232
+
+ if (!(overlay & overlay_mask) && (underlay & underlay_mask))
235
+
+ t->parms.i_flags |= TUNNEL_FAN;
237
+
+ /* Special case: overlay 0 and underlay 0 clears all mappings */
238
+
+ if (!overlay && !underlay) {
239
+
+ ipip_fan_free_map(t);
243
+
+ overlay >>= (32 - map->overlay_prefix);
244
+
+ t->fan.map[overlay] = underlay;
250
+
+static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
251
+
+ struct ip_tunnel_parm *parms)
253
+
+ struct ip_tunnel_fan_map *map;
254
+
+ struct nlattr *attr;
257
+
+ if (!data[IFLA_IPTUN_FAN_MAP])
260
+
+ if (parms->iph.daddr)
263
+
+ nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
264
+
+ map = nla_data(attr);
265
+
+ rv = ipip_fan_set_map(t, map);
273
+
static int ipip_newlink(struct net *src_net, struct net_device *dev,
274
+
struct nlattr *tb[], struct nlattr *data[])
276
+
struct ip_tunnel_parm p;
277
+
struct ip_tunnel_encap ipencap;
278
+
+ struct ip_tunnel *t = netdev_priv(dev);
281
+
if (ipip_netlink_encap_parms(data, &ipencap)) {
282
+
- struct ip_tunnel *t = netdev_priv(dev);
283
+
- int err = ip_tunnel_encap_setup(t, &ipencap);
284
+
+ err = ip_tunnel_encap_setup(t, &ipencap);
290
+
ipip_netlink_parms(data, &p);
291
+
+ err = ipip_netlink_fan(data, t, &p);
294
+
return ip_tunnel_newlink(dev, tb, &p);
297
+
@@ -398,16 +509,20 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
299
+
struct ip_tunnel_parm p;
300
+
struct ip_tunnel_encap ipencap;
301
+
+ struct ip_tunnel *t = netdev_priv(dev);
304
+
if (ipip_netlink_encap_parms(data, &ipencap)) {
305
+
- struct ip_tunnel *t = netdev_priv(dev);
306
+
- int err = ip_tunnel_encap_setup(t, &ipencap);
307
+
+ err = ip_tunnel_encap_setup(t, &ipencap);
313
+
ipip_netlink_parms(data, &p);
314
+
+ err = ipip_netlink_fan(data, t, &p);
318
+
if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
319
+
(!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
320
+
@@ -439,6 +554,8 @@ static size_t ipip_get_size(const struct net_device *dev)
321
+
nla_total_size(2) +
322
+
/* IFLA_IPTUN_ENCAP_DPORT */
323
+
nla_total_size(2) +
324
+
+ /* IFLA_IPTUN_FAN_MAP */
325
+
+ nla_total_size(sizeof(struct ip_tunnel_fan_map)) * 256 +
329
+
@@ -466,6 +583,29 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
330
+
tunnel->encap.flags))
331
+
goto nla_put_failure;
333
+
+ if (tunnel->parms.i_flags & TUNNEL_FAN) {
334
+
+ struct nlattr *fan_nest;
337
+
+ fan_nest = nla_nest_start(skb, IFLA_IPTUN_FAN_MAP);
339
+
+ goto nla_put_failure;
340
+
+ for (i = 0; i < 256; i++) {
341
+
+ if (tunnel->fan.map[i]) {
342
+
+ struct ip_tunnel_fan_map map;
344
+
+ map.underlay = htonl(tunnel->fan.map[i]);
345
+
+ map.underlay_prefix = 16;
346
+
+ map.overlay = htonl(i << 24);
347
+
+ map.overlay_prefix = 8;
348
+
+ if (nla_put(skb, IFLA_FAN_MAPPING,
349
+
+ sizeof(map), &map))
350
+
+ goto nla_put_failure;
353
+
+ nla_nest_end(skb, fan_nest);
359
+
@@ -483,6 +623,9 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
360
+
[IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 },
361
+
[IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 },
362
+
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
364
+
+ [__IFLA_IPTUN_VENDOR_BREAK ... IFLA_IPTUN_MAX] = { .type = NLA_BINARY },
365
+
+ [IFLA_IPTUN_FAN_MAP] = { .type = NLA_NESTED },
368
+
static struct rtnl_link_ops ipip_link_ops __read_mostly = {
369
+
@@ -523,6 +666,23 @@ static struct pernet_operations ipip_net_ops = {
370
+
.size = sizeof(struct ip_tunnel_net),
373
+
+#ifdef CONFIG_SYSCTL
374
+
+static struct ctl_table_header *ipip_fan_header;
375
+
+static unsigned int ipip_fan_version = 3;
377
+
+static struct ctl_table ipip_fan_sysctls[] = {
379
+
+ .procname = "version",
380
+
+ .data = &ipip_fan_version,
381
+
+ .maxlen = sizeof(ipip_fan_version),
383
+
+ .proc_handler = proc_dointvec,
388
+
+#endif /* CONFIG_SYSCTL */
390
+
static int __init ipip_init(void)
393
+
@@ -541,9 +701,22 @@ static int __init ipip_init(void)
395
+
goto rtnl_link_failed;
397
+
+#ifdef CONFIG_SYSCTL
398
+
+ ipip_fan_header = register_net_sysctl(&init_net, "net/fan",
399
+
+ ipip_fan_sysctls);
400
+
+ if (!ipip_fan_header) {
402
+
+ goto sysctl_failed;
404
+
+#endif /* CONFIG_SYSCTL */
409
+
+#ifdef CONFIG_SYSCTL
411
+
+ rtnl_link_unregister(&ipip_link_ops);
412
+
+#endif /* CONFIG_SYSCTL */
414
+
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
415
+
xfrm_tunnel_failed:
416
+
@@ -553,6 +726,9 @@ xfrm_tunnel_failed:
418
+
static void __exit ipip_fini(void)
420
+
+#ifdef CONFIG_SYSCTL
421
+
+ unregister_net_sysctl_table(ipip_fan_header);
422
+
+#endif /* CONFIG_SYSCTL */
423
+
rtnl_link_unregister(&ipip_link_ops);
424
+
if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
425
+
pr_info("%s: can't deregister tunnel\n", __func__);
429
+
From 14aba409d044e3a314c09c650e1c42de699700b8 Mon Sep 17 00:00:00 2001
430
+
From: Jay Vosburgh <jay.vosburgh@canonical.com>
431
+
Date: Wed, 11 Nov 2015 13:04:50 +0000
432
+
Subject: [PATCH] UBUNTU: SAUCE: fan: add VXLAN implementation
434
+
Generify the fan mapping support and utilise that to implement fan
435
+
mappings over vxlan transport.
437
+
Expose the existance of this functionality (when the module is loaded)
438
+
via an additional sysctl marker.
440
+
Signed-off-by: Jay Vosburgh <jay.vosburgh@canonical.com>
441
+
[apw@canonical.com: added feature marker for fan over vxlan.]
442
+
Signed-off-by: Andy Whitcroft <apw@canonical.com>
444
+
drivers/net/vxlan.c | 245 +++++++++++++++++++++++++++++++++++++++++
445
+
include/net/ip_tunnels.h | 19 +++-
446
+
include/net/vxlan.h | 2 +
447
+
include/uapi/linux/if_link.h | 1 +
448
+
include/uapi/linux/if_tunnel.h | 2 +-
449
+
net/ipv4/ip_tunnel.c | 7 +-
450
+
net/ipv4/ipip.c | 242 +++++++++++++++++++++++++++++++---------
451
+
7 files changed, 453 insertions(+), 65 deletions(-)
453
+
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
454
+
index 405a7b6..a17cfd0 100644
455
+
--- a/drivers/net/vxlan.c
456
+
+++ b/drivers/net/vxlan.c
458
+
#include <linux/udp.h>
459
+
#include <linux/igmp.h>
460
+
#include <linux/etherdevice.h>
461
+
+#include <linux/inetdevice.h>
462
+
#include <linux/if_ether.h>
463
+
#include <linux/if_vlan.h>
464
+
#include <linux/hash.h>
465
+
@@ -106,6 +107,167 @@ static inline bool vxlan_collect_metadata(struct vxlan_sock *vs)
466
+
ip_tunnel_collect_metadata();
469
+
+static struct ip_fan_map *vxlan_fan_find_map(struct vxlan_dev *vxlan, __be32 daddr)
471
+
+ struct ip_fan_map *fan_map;
474
+
+ list_for_each_entry_rcu(fan_map, &vxlan->fan.fan_maps, list) {
475
+
+ if (fan_map->overlay ==
476
+
+ (daddr & inet_make_mask(fan_map->overlay_prefix))) {
477
+
+ rcu_read_unlock();
481
+
+ rcu_read_unlock();
486
+
+static void vxlan_fan_flush_map(struct vxlan_dev *vxlan)
488
+
+ struct ip_fan_map *fan_map;
490
+
+ list_for_each_entry_rcu(fan_map, &vxlan->fan.fan_maps, list) {
491
+
+ list_del_rcu(&fan_map->list);
492
+
+ kfree_rcu(fan_map, rcu);
496
+
+static int vxlan_fan_del_map(struct vxlan_dev *vxlan, __be32 overlay)
498
+
+ struct ip_fan_map *fan_map;
500
+
+ fan_map = vxlan_fan_find_map(vxlan, overlay);
504
+
+ list_del_rcu(&fan_map->list);
505
+
+ kfree_rcu(fan_map, rcu);
510
+
+static int vxlan_fan_add_map(struct vxlan_dev *vxlan, struct ifla_fan_map *map)
512
+
+ __be32 overlay_mask, underlay_mask;
513
+
+ struct ip_fan_map *fan_map;
515
+
+ overlay_mask = inet_make_mask(map->overlay_prefix);
516
+
+ underlay_mask = inet_make_mask(map->underlay_prefix);
518
+
+ netdev_dbg(vxlan->dev, "vfam: map: o %x/%d u %x/%d om %x um %x\n",
519
+
+ map->overlay, map->overlay_prefix,
520
+
+ map->underlay, map->underlay_prefix,
521
+
+ overlay_mask, underlay_mask);
523
+
+ if ((map->overlay & ~overlay_mask) || (map->underlay & ~underlay_mask))
526
+
+ if (!(map->overlay & overlay_mask) && (map->underlay & underlay_mask))
529
+
+ /* Special case: overlay 0 and underlay 0: flush all mappings */
530
+
+ if (!map->overlay && !map->underlay) {
531
+
+ vxlan_fan_flush_map(vxlan);
535
+
+ /* Special case: overlay set and underlay 0: clear map for overlay */
536
+
+ if (!map->underlay)
537
+
+ return vxlan_fan_del_map(vxlan, map->overlay);
539
+
+ if (vxlan_fan_find_map(vxlan, map->overlay))
542
+
+ fan_map = kmalloc(sizeof(*fan_map), GFP_KERNEL);
543
+
+ fan_map->underlay = map->underlay;
544
+
+ fan_map->overlay = map->overlay;
545
+
+ fan_map->underlay_prefix = map->underlay_prefix;
546
+
+ fan_map->overlay_mask = ntohl(overlay_mask);
547
+
+ fan_map->overlay_prefix = map->overlay_prefix;
549
+
+ list_add_tail_rcu(&fan_map->list, &vxlan->fan.fan_maps);
554
+
+static int vxlan_parse_fan_map(struct nlattr *data[], struct vxlan_dev *vxlan)
556
+
+ struct ifla_fan_map *map;
557
+
+ struct nlattr *attr;
560
+
+ nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
561
+
+ map = nla_data(attr);
562
+
+ rv = vxlan_fan_add_map(vxlan, map);
570
+
+static int vxlan_fan_build_rdst(struct vxlan_dev *vxlan, struct sk_buff *skb,
571
+
+ struct vxlan_rdst *fan_rdst)
573
+
+ struct ip_fan_map *f_map;
574
+
+ union vxlan_addr *va;
575
+
+ u32 daddr, underlay;
576
+
+ struct arphdr *arp;
578
+
+ struct ethhdr *eth;
579
+
+ struct iphdr *iph;
581
+
+ eth = eth_hdr(skb);
582
+
+ switch (eth->h_proto) {
583
+
+ case htons(ETH_P_IP):
584
+
+ iph = ip_hdr(skb);
587
+
+ daddr = iph->daddr;
589
+
+ case htons(ETH_P_ARP):
590
+
+ arp = arp_hdr(skb);
593
+
+ arp_ptr = arp + 1;
594
+
+ netdev_dbg(vxlan->dev,
595
+
+ "vfbr: arp sha %pM sip %pI4 tha %pM tip %pI4\n",
596
+
+ arp_ptr, arp_ptr + skb->dev->addr_len,
597
+
+ arp_ptr + skb->dev->addr_len + 4,
598
+
+ arp_ptr + (skb->dev->addr_len * 2) + 4);
599
+
+ arp_ptr += (skb->dev->addr_len * 2) + 4;
600
+
+ memcpy(&daddr, arp_ptr, 4);
603
+
+ netdev_dbg(vxlan->dev, "vfbr: unknown eth p %x\n", eth->h_proto);
607
+
+ f_map = vxlan_fan_find_map(vxlan, daddr);
611
+
+ daddr = ntohl(daddr);
612
+
+ underlay = ntohl(f_map->underlay);
616
+
+ memset(fan_rdst, 0, sizeof(*fan_rdst));
617
+
+ va = &fan_rdst->remote_ip;
618
+
+ va->sa.sa_family = AF_INET;
619
+
+ fan_rdst->remote_vni = vxlan->default_dst.remote_vni;
620
+
+ va->sin.sin_addr.s_addr = htonl(underlay |
621
+
+ ((daddr & ~f_map->overlay_mask) >>
622
+
+ (32 - f_map->overlay_prefix -
623
+
+ (32 - f_map->underlay_prefix))));
624
+
+ netdev_dbg(vxlan->dev, "vfbr: daddr %x ul %x dst %x\n",
625
+
+ daddr, underlay, va->sin.sin_addr.s_addr);
630
+
#if IS_ENABLED(CONFIG_IPV6)
632
+
bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b)
633
+
@@ -2029,6 +2191,13 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
637
+
+ if (fan_has_map(&vxlan->fan) && rt->rt_flags & RTCF_LOCAL) {
638
+
+ netdev_dbg(dev, "discard fan to localhost %pI4\n",
639
+
+ &dst->sin.sin_addr.s_addr);
644
+
/* Bypass encapsulation if the destination is local */
645
+
if (rt->rt_flags & RTCF_LOCAL &&
646
+
!(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
647
+
@@ -2169,6 +2338,20 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
648
+
return NETDEV_TX_OK;
651
+
+ if (fan_has_map(&vxlan->fan)) {
652
+
+ struct vxlan_rdst fan_rdst;
654
+
+ netdev_dbg(vxlan->dev, "vxlan_xmit p %x d %pM\n",
655
+
+ eth->h_proto, eth->h_dest);
656
+
+ if (vxlan_fan_build_rdst(vxlan, skb, &fan_rdst)) {
657
+
+ dev->stats.tx_dropped++;
659
+
+ return NETDEV_TX_OK;
661
+
+ vxlan_xmit_one(skb, dev, &fan_rdst, 0);
662
+
+ return NETDEV_TX_OK;
665
+
f = vxlan_find_mac(vxlan, eth->h_dest);
668
+
@@ -2532,6 +2715,8 @@ static void vxlan_setup(struct net_device *dev)
670
+
for (h = 0; h < FDB_HASH_SIZE; ++h)
671
+
INIT_HLIST_HEAD(&vxlan->fdb_head[h]);
673
+
+ INIT_LIST_HEAD(&vxlan->fan.fan_maps);
676
+
static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
677
+
@@ -2881,6 +3066,7 @@ EXPORT_SYMBOL_GPL(vxlan_dev_create);
678
+
static int vxlan_newlink(struct net *src_net, struct net_device *dev,
679
+
struct nlattr *tb[], struct nlattr *data[])
681
+
+ struct vxlan_dev *vxlan = netdev_priv(dev);
682
+
struct vxlan_config conf;
685
+
@@ -2899,6 +3085,12 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
686
+
conf.remote_ip.sa.sa_family = AF_INET6;
689
+
+ if (data[IFLA_VXLAN_FAN_MAP]) {
690
+
+ err = vxlan_parse_fan_map(data, vxlan);
695
+
if (data[IFLA_VXLAN_LOCAL]) {
696
+
conf.saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]);
697
+
conf.saddr.sa.sa_family = AF_INET;
698
+
@@ -3037,6 +3229,7 @@ static size_t vxlan_get_size(const struct net_device *dev)
699
+
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */
700
+
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_TX */
701
+
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */
702
+
+ nla_total_size(sizeof(struct ip_fan_map) * 256) +
706
+
@@ -3083,6 +3276,26 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
710
+
+ if (fan_has_map(&vxlan->fan)) {
711
+
+ struct nlattr *fan_nest;
712
+
+ struct ip_fan_map *fan_map;
714
+
+ fan_nest = nla_nest_start(skb, IFLA_VXLAN_FAN_MAP);
716
+
+ goto nla_put_failure;
717
+
+ list_for_each_entry_rcu(fan_map, &vxlan->fan.fan_maps, list) {
718
+
+ struct ifla_fan_map map;
720
+
+ map.underlay = fan_map->underlay;
721
+
+ map.underlay_prefix = fan_map->underlay_prefix;
722
+
+ map.overlay = fan_map->overlay;
723
+
+ map.overlay_prefix = fan_map->overlay_prefix;
724
+
+ if (nla_put(skb, IFLA_FAN_MAPPING, sizeof(map), &map))
725
+
+ goto nla_put_failure;
727
+
+ nla_nest_end(skb, fan_nest);
730
+
if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->cfg.ttl) ||
731
+
nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->cfg.tos) ||
732
+
nla_put_u8(skb, IFLA_VXLAN_LEARNING,
733
+
@@ -3201,6 +3414,22 @@ static __net_init int vxlan_init_net(struct net *net)
737
+
+#ifdef CONFIG_SYSCTL
738
+
+static struct ctl_table_header *vxlan_fan_header;
739
+
+static unsigned int vxlan_fan_version = 4;
741
+
+static struct ctl_table vxlan_fan_sysctls[] = {
743
+
+ .procname = "vxlan",
744
+
+ .data = &vxlan_fan_version,
745
+
+ .maxlen = sizeof(vxlan_fan_version),
747
+
+ .proc_handler = proc_dointvec,
751
+
+#endif /* CONFIG_SYSCTL */
753
+
static void __net_exit vxlan_exit_net(struct net *net)
755
+
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
756
+
@@ -3256,7 +3485,20 @@ static int __init vxlan_init_module(void)
760
+
+#ifdef CONFIG_SYSCTL
761
+
+ vxlan_fan_header = register_net_sysctl(&init_net, "net/fan",
762
+
+ vxlan_fan_sysctls);
763
+
+ if (!vxlan_fan_header) {
765
+
+ goto sysctl_failed;
767
+
+#endif /* CONFIG_SYSCTL */
770
+
+#ifdef CONFIG_SYSCTL
772
+
+ rtnl_link_unregister(&vxlan_link_ops);
773
+
+#endif /* CONFIG_SYSCTL */
775
+
unregister_netdevice_notifier(&vxlan_notifier_block);
777
+
@@ -3269,6 +3511,9 @@ late_initcall(vxlan_init_module);
779
+
static void __exit vxlan_cleanup_module(void)
781
+
+#ifdef CONFIG_SYSCTL
782
+
+ unregister_net_sysctl_table(vxlan_fan_header);
783
+
+#endif /* CONFIG_SYSCTL */
784
+
rtnl_link_unregister(&vxlan_link_ops);
785
+
unregister_netdevice_notifier(&vxlan_notifier_block);
786
+
destroy_workqueue(vxlan_wq);
787
+
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
788
+
index 47fec59..28a38e5 100644
789
+
--- a/include/net/ip_tunnels.h
790
+
+++ b/include/net/ip_tunnels.h
791
+
@@ -100,9 +100,18 @@ struct metadata_dst;
793
+
#define FAN_OVERLAY_CNT 256
795
+
+struct ip_fan_map {
798
+
+ u16 underlay_prefix;
799
+
+ u16 overlay_prefix;
800
+
+ u32 overlay_mask;
801
+
+ struct list_head list;
802
+
+ struct rcu_head rcu;
805
+
struct ip_tunnel_fan {
806
+
-/* u32 __rcu *map;*/
807
+
- u32 map[FAN_OVERLAY_CNT];
808
+
+ struct list_head fan_maps;
812
+
@@ -157,7 +166,11 @@ struct ip_tunnel {
813
+
#define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000)
815
+
#define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT)
816
+
-#define TUNNEL_FAN __cpu_to_be16(0x4000)
818
+
+static inline int fan_has_map(const struct ip_tunnel_fan *fan)
820
+
+ return !list_empty(&fan->fan_maps);
823
+
struct tnl_ptk_info {
825
+
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
826
+
index e289ada..542f421 100644
827
+
--- a/include/net/vxlan.h
828
+
+++ b/include/net/vxlan.h
829
+
@@ -161,6 +161,8 @@ struct vxlan_dev {
830
+
struct vxlan_rdst default_dst; /* default destination */
831
+
u32 flags; /* VXLAN_F_* in vxlan.h */
833
+
+ struct ip_tunnel_fan fan;
835
+
struct timer_list age_timer;
836
+
spinlock_t hash_lock;
837
+
unsigned int addrcnt;
838
+
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
839
+
index 5ad5737..6cde3bf 100644
840
+
--- a/include/uapi/linux/if_link.h
841
+
+++ b/include/uapi/linux/if_link.h
842
+
@@ -443,6 +443,7 @@ enum {
844
+
IFLA_VXLAN_REMCSUM_NOPARTIAL,
845
+
IFLA_VXLAN_COLLECT_METADATA,
846
+
+ IFLA_VXLAN_FAN_MAP = 33,
849
+
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
850
+
diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
851
+
index 85a3e4b..d36b150 100644
852
+
--- a/include/uapi/linux/if_tunnel.h
853
+
+++ b/include/uapi/linux/if_tunnel.h
854
+
@@ -145,7 +145,7 @@ enum {
856
+
#define IFLA_FAN_MAX (__IFLA_FAN_MAX - 1)
858
+
-struct ip_tunnel_fan_map {
859
+
+struct ifla_fan_map {
862
+
__u16 underlay_prefix;
863
+
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
864
+
index 7a6174b..c821bf1 100644
865
+
--- a/net/ipv4/ip_tunnel.c
866
+
+++ b/net/ipv4/ip_tunnel.c
867
+
@@ -1110,11 +1110,6 @@ out:
869
+
EXPORT_SYMBOL_GPL(ip_tunnel_newlink);
871
+
-static int ip_tunnel_is_fan(struct ip_tunnel *tunnel)
873
+
- return tunnel->parms.i_flags & TUNNEL_FAN;
876
+
int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
877
+
struct ip_tunnel_parm *p)
879
+
@@ -1124,7 +1119,7 @@ int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
880
+
struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id);
882
+
if (dev == itn->fb_tunnel_dev)
883
+
- return ip_tunnel_is_fan(tunnel) ? 0 : -EINVAL;
884
+
+ return fan_has_map(&tunnel->fan) ? 0 : -EINVAL;
886
+
t = ip_tunnel_find(itn, p, dev->type);
888
+
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
889
+
index 56e8984..3877b0e 100644
890
+
--- a/net/ipv4/ipip.c
891
+
+++ b/net/ipv4/ipip.c
892
+
@@ -108,6 +108,7 @@
893
+
#include <linux/netfilter_ipv4.h>
894
+
#include <linux/if_ether.h>
895
+
#include <linux/inetdevice.h>
896
+
+#include <linux/rculist.h>
898
+
#include <net/sock.h>
899
+
#include <net/ip.h>
900
+
@@ -209,37 +210,144 @@ drop:
904
+
-static int ipip_tunnel_is_fan(struct ip_tunnel *tunnel)
905
+
+static struct ip_fan_map *ipip_fan_find_map(struct ip_tunnel *t, __be32 daddr)
907
+
- return tunnel->parms.i_flags & TUNNEL_FAN;
908
+
+ struct ip_fan_map *fan_map;
911
+
+ list_for_each_entry_rcu(fan_map, &t->fan.fan_maps, list) {
912
+
+ if (fan_map->overlay ==
913
+
+ (daddr & inet_make_mask(fan_map->overlay_prefix))) {
914
+
+ rcu_read_unlock();
918
+
+ rcu_read_unlock();
924
+
- * Determine fan tunnel endpoint to send packet to, based on the inner IP
925
+
- * address. For an overlay (inner) address Y.A.B.C, the transformation is
926
+
- * F.G.A.B, where "F" and "G" are the first two octets of the underlay
927
+
- * network (the network portion of a /16), "A" and "B" are the low order
928
+
- * two octets of the underlay network host (the host portion of a /16),
929
+
- * and "Y" is a configured first octet of the overlay network.
930
+
+/* Determine fan tunnel endpoint to send packet to, based on the inner IP
933
+
+ * Given a /8 overlay and /16 underlay, for an overlay (inner) address
934
+
+ * Y.A.B.C, the transformation is F.G.A.B, where "F" and "G" are the first
935
+
+ * two octets of the underlay network (the network portion of a /16), "A"
936
+
+ * and "B" are the low order two octets of the underlay network host (the
937
+
+ * host portion of a /16), and "Y" is a configured first octet of the
938
+
+ * overlay network.
940
+
+ * E.g., underlay host 10.88.3.4/16 with an overlay of 99.0.0.0/8 would
941
+
+ * host overlay subnet 99.3.4.0/24. An overlay network datagram from
942
+
+ * 99.3.4.5 to 99.6.7.8, would be directed to underlay host 10.88.6.7,
943
+
+ * which hosts overlay network subnet 99.6.7.0/24. This transformation is
944
+
+ * described in detail further below.
946
+
+ * Using netmasks for the overlay and underlay other than /8 and /16, as
947
+
+ * shown above, can yield larger (or smaller) overlay subnets, with the
948
+
+ * trade-off of allowing fewer (or more) underlay hosts to participate.
950
+
+ * The size of each overlay network subnet is defined by the total of the
951
+
+ * network mask of the overlay plus the size of host portion of the
952
+
+ * underlay network. In the above example, /8 + /16 = /24.
954
+
+ * E.g., consider underlay host 10.99.238.5/20 and overlay 99.0.0.0/8. In
955
+
+ * this case, the network portion of the underlay is 10.99.224.0/20, and
956
+
+ * the host portion is 0.0.14.5 (12 bits). To determine the overlay
957
+
+ * network subnet, the 12 bits of host portion are left shifted 12 bits
958
+
+ * (/20 - /8) and ORed with the overlay subnet prefix. This yields an
959
+
+ * overlay subnet of 99.224.80/20, composed of 8 bits overlay, followed by
960
+
+ * 12 bits underlay. This yields 12 bits in the overlay network portion,
961
+
+ * allowing for 4094 addresses in each overlay network subnet. The
962
+
+ * trade-off is that fewer hosts may participate in the underlay network,
963
+
+ * as its host address size has shrunk from 16 bits (65534 addresses) in
964
+
+ * the first example to 12 bits (4094 addresses) here.
966
+
+ * For fewer hosts per overlay subnet (permitting a larger number of
967
+
+ * underlay hosts to participate), the underlay netmask may be made
970
+
+ * E.g., underlay host 10.111.1.2/12 (network 10.96.0.0/12, host portion
971
+
+ * is 0.15.1.2, 20 bits) with an overlay of 33.0.0.0/8 would left shift
972
+
+ * the 20 bits of host by 4 (so that it's highest order bit is adjacent to
973
+
+ * the lowest order bit of the /8 overlay). This yields an overlay subnet
974
+
+ * of 33.240.16.32/28 (8 bits overlay, 20 bits from the host portion of
975
+
+ * the underlay). This provides more addresses for the underlay network
976
+
+ * (approximately 2^20), but each host's segment of the overlay provides
977
+
+ * only 4 bits of addresses (14 usable).
979
+
+ * It is also possible to adjust the overlay subnet.
981
+
+ * For an overlay of 240.0.0.0/5 and underlay of 10.88.0.0/20, consider
982
+
+ * underlay host 10.88.129.2; the 12 bits of host, 0.0.1.2, are left
983
+
+ * shifted 15 bits (/20 - /5), yielding an overlay network of
984
+
+ * 240.129.0.0/17. An underlay host of 10.88.244.215 would yield an
985
+
+ * overlay network of 242.107.128.0/17.
987
+
+ * For an overlay of 100.64.0.0/10 and underlay of 10.224.220.0/24, for
988
+
+ * underlay host 10.224.220.10, the underlay host portion (.10) is left
989
+
+ * shifted 14 bits, yielding an overlay network subnet of 100.66.128.0/18.
990
+
+ * This would permit 254 addresses on the underlay, with each overlay
991
+
+ * segment providing approximately 2^14 - 2 addresses (16382).
993
+
+ * For packets being encapsulated, the overlay network destination IP
994
+
+ * address is deconstructed into its overlay and underlay-derived
995
+
+ * portions. The underlay portion (determined by the overlay mask and
996
+
+ * overlay subnet mask) is right shifted according to the size of the
997
+
+ * underlay network mask. This value is then ORed with the network
998
+
+ * portion of the underlay network to produce the underlay network
999
+
+ * destination for the encapsulated datagram.
1001
+
+ * For example, using the initial example of underlay 10.88.3.4/16 and
1002
+
+ * overlay 99.0.0.0/8, with underlay host 10.88.3.4/16 providing overlay
1003
+
+ * subnet 99.3.4.0/24 with specfic host 99.3.4.5. A datagram from
1004
+
+ * 99.3.4.5 to 99.6.7.8 would first have the underlay host derived portion
1005
+
+ * of the address extracted. This is a number of bits equal to underlay
1006
+
+ * network host portion. In the destination address, the highest order of
1007
+
+ * these bits is one bit lower than the lowest order bit from the overlay
1010
+
+ * Using the sample value, 99.6.7.8, the overlay mask is /8, and the
1011
+
+ * underlay mask is /16 (leaving 16 bits for the host portion). The bits
1012
+
+ * to be shifted are the middle two octets, 0.6.7.0, as this is 99.6.7.8
1013
+
+ * ANDed with the mask 0x00ffff00 (which is 16 bits, the highest order of
1014
+
+ * which is 1 bit lower than the lowest order overlay address bit).
1016
+
- * E.g., underlay host 10.88.3.4 with an overlay of 99 would host overlay
1017
+
- * subnet 99.3.4.0/24. An overlay network datagram from 99.3.4.5 to
1018
+
- * 99.6.7.8, would be directed to underlay host 10.88.6.7, which hosts
1019
+
- * overlay network 99.6.7.0/24.
1020
+
+ * These octets, 0.6.7.0, are then right shifted 8 bits, yielding 0.0.6.7.
1021
+
+ * This value is then ORed with the underlay network portion,
1022
+
+ * 10.88.0.0/16, providing 10.88.6.7 as the final underlay destination for
1023
+
+ * the encapuslated datagram.
1025
+
+ * Another transform using the final example: overlay 100.64.0.0/10 and
1026
+
+ * underlay 10.224.220.0/24. Consider overlay address 100.66.128.1
1027
+
+ * sending a datagram to 100.66.200.5. In this case, 8 bits (the host
1028
+
+ * portion size of 10.224.220.0/24) beginning after the 100.64/10 overlay
1029
+
+ * prefix are masked off, yielding 0.2.192.0. This is right shifted 14
1030
+
+ * (32 - 10 - (32 - 24), i.e., the number of bits between the overlay
1031
+
+ * network portion and the underlay host portion) bits, yielding 0.0.0.11.
1032
+
+ * This is ORed with the underlay network portion, 10.224.220.0/24, giving
1033
+
+ * the underlay destination of 10.224.220.11 for overlay destination
1036
+
static int ipip_build_fan_iphdr(struct ip_tunnel *tunnel, struct sk_buff *skb, struct iphdr *iph)
1038
+
- unsigned int overlay;
1039
+
+ struct ip_fan_map *f_map;
1040
+
u32 daddr, underlay;
1042
+
+ f_map = ipip_fan_find_map(tunnel, ip_hdr(skb)->daddr);
1046
+
daddr = ntohl(ip_hdr(skb)->daddr);
1047
+
- overlay = daddr >> 24;
1048
+
- underlay = tunnel->fan.map[overlay];
1049
+
+ underlay = ntohl(f_map->underlay);
1053
+
*iph = tunnel->parms.iph;
1054
+
- iph->daddr = htonl(underlay | ((daddr >> 8) & 0x0000ffff));
1055
+
+ iph->daddr = htonl(underlay |
1056
+
+ ((daddr & ~f_map->overlay_mask) >>
1057
+
+ (32 - f_map->overlay_prefix -
1058
+
+ (32 - f_map->underlay_prefix))));
1062
+
@@ -260,7 +368,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
1066
+
- if (ipip_tunnel_is_fan(tunnel)) {
1067
+
+ if (fan_has_map(&tunnel->fan)) {
1068
+
if (ipip_build_fan_iphdr(tunnel, skb, &fiph))
1071
+
@@ -325,6 +433,8 @@ static const struct net_device_ops ipip_netdev_ops = {
1073
+
static void ipip_tunnel_setup(struct net_device *dev)
1075
+
+ struct ip_tunnel *t = netdev_priv(dev);
1077
+
dev->netdev_ops = &ipip_netdev_ops;
1079
+
dev->type = ARPHRD_TUNNEL;
1080
+
@@ -336,6 +446,7 @@ static void ipip_tunnel_setup(struct net_device *dev)
1081
+
dev->features |= IPIP_FEATURES;
1082
+
dev->hw_features |= IPIP_FEATURES;
1083
+
ip_tunnel_setup(dev, ipip_net_id);
1084
+
+ INIT_LIST_HEAD(&t->fan.fan_maps);
1087
+
static int ipip_tunnel_init(struct net_device *dev)
1088
+
@@ -419,41 +530,65 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
1092
+
-static void ipip_fan_free_map(struct ip_tunnel *t)
1093
+
+static void ipip_fan_flush_map(struct ip_tunnel *t)
1095
+
- memset(&t->fan.map, 0, sizeof(t->fan.map));
1096
+
+ struct ip_fan_map *fan_map;
1098
+
+ list_for_each_entry_rcu(fan_map, &t->fan.fan_maps, list) {
1099
+
+ list_del_rcu(&fan_map->list);
1100
+
+ kfree_rcu(fan_map, rcu);
1104
+
-static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
1105
+
+static int ipip_fan_del_map(struct ip_tunnel *t, __be32 overlay)
1107
+
- u32 overlay, overlay_mask, underlay, underlay_mask;
1108
+
+ struct ip_fan_map *fan_map;
1110
+
- if ((map->underlay_prefix && map->underlay_prefix != 16) ||
1111
+
- (map->overlay_prefix && map->overlay_prefix != 8))
1113
+
+ fan_map = ipip_fan_find_map(t, overlay);
1117
+
+ list_del_rcu(&fan_map->list);
1118
+
+ kfree_rcu(fan_map, rcu);
1120
+
- overlay = ntohl(map->overlay);
1121
+
- overlay_mask = ntohl(inet_make_mask(map->overlay_prefix));
1125
+
- underlay = ntohl(map->underlay);
1126
+
- underlay_mask = ntohl(inet_make_mask(map->underlay_prefix));
1127
+
+static int ipip_fan_add_map(struct ip_tunnel *t, struct ifla_fan_map *map)
1129
+
+ __be32 overlay_mask, underlay_mask;
1130
+
+ struct ip_fan_map *fan_map;
1132
+
- if ((overlay & ~overlay_mask) || (underlay & ~underlay_mask))
1134
+
+ overlay_mask = inet_make_mask(map->overlay_prefix);
1135
+
+ underlay_mask = inet_make_mask(map->underlay_prefix);
1137
+
- if (!(overlay & overlay_mask) && (underlay & underlay_mask))
1138
+
+ if ((map->overlay & ~overlay_mask) || (map->underlay & ~underlay_mask))
1141
+
- t->parms.i_flags |= TUNNEL_FAN;
1142
+
+ if (!(map->overlay & overlay_mask) && (map->underlay & underlay_mask))
1145
+
- /* Special case: overlay 0 and underlay 0 clears all mappings */
1146
+
- if (!overlay && !underlay) {
1147
+
- ipip_fan_free_map(t);
1148
+
+ /* Special case: overlay 0 and underlay 0: flush all mappings */
1149
+
+ if (!map->overlay && !map->underlay) {
1150
+
+ ipip_fan_flush_map(t);
1154
+
+ /* Special case: overlay set and underlay 0: clear map for overlay */
1155
+
+ if (!map->underlay)
1156
+
+ return ipip_fan_del_map(t, map->overlay);
1158
+
+ if (ipip_fan_find_map(t, map->overlay))
1161
+
+ fan_map = kmalloc(sizeof(*fan_map), GFP_KERNEL);
1162
+
+ fan_map->underlay = map->underlay;
1163
+
+ fan_map->overlay = map->overlay;
1164
+
+ fan_map->underlay_prefix = map->underlay_prefix;
1165
+
+ fan_map->overlay_mask = ntohl(overlay_mask);
1166
+
+ fan_map->overlay_prefix = map->overlay_prefix;
1168
+
- overlay >>= (32 - map->overlay_prefix);
1169
+
- t->fan.map[overlay] = underlay;
1170
+
+ list_add_tail_rcu(&fan_map->list, &t->fan.fan_maps);
1174
+
@@ -462,7 +597,7 @@ static int ipip_fan_set_map(struct ip_tunnel *t, struct ip_tunnel_fan_map *map)
1175
+
static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
1176
+
struct ip_tunnel_parm *parms)
1178
+
- struct ip_tunnel_fan_map *map;
1179
+
+ struct ifla_fan_map *map;
1180
+
struct nlattr *attr;
1183
+
@@ -474,7 +609,7 @@ static int ipip_netlink_fan(struct nlattr *data[], struct ip_tunnel *t,
1185
+
nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
1186
+
map = nla_data(attr);
1187
+
- rv = ipip_fan_set_map(t, map);
1188
+
+ rv = ipip_fan_add_map(t, map);
1192
+
@@ -555,7 +690,7 @@ static size_t ipip_get_size(const struct net_device *dev)
1193
+
/* IFLA_IPTUN_ENCAP_DPORT */
1194
+
nla_total_size(2) +
1195
+
/* IFLA_IPTUN_FAN_MAP */
1196
+
- nla_total_size(sizeof(struct ip_tunnel_fan_map)) * 256 +
1197
+
+ nla_total_size(sizeof(struct ifla_fan_map)) * 256 +
1201
+
@@ -583,25 +718,22 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
1202
+
tunnel->encap.flags))
1203
+
goto nla_put_failure;
1205
+
- if (tunnel->parms.i_flags & TUNNEL_FAN) {
1206
+
+ if (fan_has_map(&tunnel->fan)) {
1207
+
struct nlattr *fan_nest;
1209
+
+ struct ip_fan_map *fan_map;
1211
+
fan_nest = nla_nest_start(skb, IFLA_IPTUN_FAN_MAP);
1213
+
goto nla_put_failure;
1214
+
- for (i = 0; i < 256; i++) {
1215
+
- if (tunnel->fan.map[i]) {
1216
+
- struct ip_tunnel_fan_map map;
1218
+
- map.underlay = htonl(tunnel->fan.map[i]);
1219
+
- map.underlay_prefix = 16;
1220
+
- map.overlay = htonl(i << 24);
1221
+
- map.overlay_prefix = 8;
1222
+
- if (nla_put(skb, IFLA_FAN_MAPPING,
1223
+
- sizeof(map), &map))
1224
+
- goto nla_put_failure;
1226
+
+ list_for_each_entry_rcu(fan_map, &tunnel->fan.fan_maps, list) {
1227
+
+ struct ifla_fan_map map;
1229
+
+ map.underlay = fan_map->underlay;
1230
+
+ map.underlay_prefix = fan_map->underlay_prefix;
1231
+
+ map.overlay = fan_map->overlay;
1232
+
+ map.overlay_prefix = fan_map->overlay_prefix;
1233
+
+ if (nla_put(skb, IFLA_FAN_MAPPING, sizeof(map), &map))
1234
+
+ goto nla_put_failure;
1236
+
nla_nest_end(skb, fan_nest);