3558b0e32e92dcaa3966e237a72a1ccf5ca6f05c
[sliver-openvswitch.git] / datapath / vport-vxlan.c
1 /*
2  * Copyright (c) 2011 Nicira, Inc.
3  * Copyright (c) 2012 Cisco Systems, Inc.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public
7  * License as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA
18  */
19
20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
22 #include <linux/version.h>
23 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
24
25 #include <linux/in.h>
26 #include <linux/ip.h>
27 #include <linux/net.h>
28 #include <linux/rculist.h>
29 #include <linux/udp.h>
30
31 #include <net/icmp.h>
32 #include <net/ip.h>
33 #include <net/udp.h>
34
35 #include "datapath.h"
36 #include "tunnel.h"
37 #include "vport.h"
38
39 #define VXLAN_FLAGS 0x08000000  /* struct vxlanhdr.vx_flags required value. */
40
41 /**
42  * struct vxlanhdr - VXLAN header
43  * @vx_flags: Must have the exact value %VXLAN_FLAGS.
44  * @vx_vni: VXLAN Network Identifier (VNI) in top 24 bits, low 8 bits zeroed.
45  */
46 struct vxlanhdr {
47         __be32 vx_flags;
48         __be32 vx_vni;
49 };
50
51 #define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
52
53 /**
54  * struct vxlan_port - Keeps track of open UDP ports
55  * @dst_port: vxlan UDP port no.
56  * @list: list element in @vxlan_ports.
57  * @vxlan_rcv_socket: The socket created for this port number.
58  * @name: vport name.
59  */
60 struct vxlan_port {
61         __be16 dst_port;
62         struct list_head list;
63         struct socket *vxlan_rcv_socket;
64         char name[IFNAMSIZ];
65 };
66
67 static LIST_HEAD(vxlan_ports);
68
69 static inline struct vxlan_port *vxlan_vport(const struct vport *vport)
70 {
71         return vport_priv(vport);
72 }
73
74 static struct vxlan_port *vxlan_find_port(struct net *net, __be16 port)
75 {
76         struct vxlan_port *vxlan_port;
77
78         list_for_each_entry_rcu(vxlan_port, &vxlan_ports, list) {
79
80                 if (vxlan_port->dst_port == port &&
81                         net_eq(sock_net(vxlan_port->vxlan_rcv_socket->sk), net))
82                         return vxlan_port;
83         }
84
85         return NULL;
86 }
87
88 static inline struct vxlanhdr *vxlan_hdr(const struct sk_buff *skb)
89 {
90         return (struct vxlanhdr *)(udp_hdr(skb) + 1);
91 }
92
93 static void vxlan_build_header(const struct vport *vport,
94                                struct sk_buff *skb,
95                                int tunnel_hlen)
96 {
97         struct vxlan_port *vxlan_port = vxlan_vport(vport);
98         struct udphdr *udph = udp_hdr(skb);
99         struct vxlanhdr *vxh = (struct vxlanhdr *)(udph + 1);
100         const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
101
102         udph->dest = vxlan_port->dst_port;
103         udph->source = htons(ovs_tnl_get_src_port(skb));
104         udph->check = 0;
105         udph->len = htons(skb->len - skb_transport_offset(skb));
106
107         vxh->vx_flags = htonl(VXLAN_FLAGS);
108         vxh->vx_vni = htonl(be64_to_cpu(tun_key->tun_id) << 8);
109 }
110
111 /* Called with rcu_read_lock and BH disabled. */
112 static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
113 {
114         struct vxlan_port *vxlan_vport;
115         struct vxlanhdr *vxh;
116         struct iphdr *iph;
117         struct ovs_key_ipv4_tunnel tun_key;
118         __be64 key;
119
120         vxlan_vport = vxlan_find_port(dev_net(skb->dev), udp_hdr(skb)->dest);
121         if (unlikely(!vxlan_vport))
122                 goto error;
123
124         if (unlikely(!pskb_may_pull(skb, VXLAN_HLEN + ETH_HLEN)))
125                 goto error;
126
127         vxh = vxlan_hdr(skb);
128         if (unlikely(vxh->vx_flags != htonl(VXLAN_FLAGS) ||
129                      vxh->vx_vni & htonl(0xff)))
130                 goto error;
131
132         __skb_pull(skb, VXLAN_HLEN);
133         skb_postpull_rcsum(skb, skb_transport_header(skb), VXLAN_HLEN + ETH_HLEN);
134
135         key = cpu_to_be64(ntohl(vxh->vx_vni) >> 8);
136
137         /* Save outer tunnel values */
138         iph = ip_hdr(skb);
139         tnl_tun_key_init(&tun_key, iph, key, OVS_TNL_F_KEY);
140         OVS_CB(skb)->tun_key = &tun_key;
141
142         ovs_tnl_rcv(vport_from_priv(vxlan_vport), skb);
143         goto out;
144
145 error:
146         kfree_skb(skb);
147 out:
148         return 0;
149 }
150
151 /* Random value.  Irrelevant as long as it's not 0 since we set the handler. */
152 #define UDP_ENCAP_VXLAN 1
153 static int vxlan_socket_init(struct vxlan_port *vxlan_port, struct net *net)
154 {
155         struct sockaddr_in sin;
156         int err;
157
158         err = sock_create_kern(AF_INET, SOCK_DGRAM, 0,
159                                &vxlan_port->vxlan_rcv_socket);
160         if (err)
161                 goto error;
162
163         /* release net ref. */
164         sk_change_net(vxlan_port->vxlan_rcv_socket->sk, net);
165
166         sin.sin_family = AF_INET;
167         sin.sin_addr.s_addr = htonl(INADDR_ANY);
168         sin.sin_port = vxlan_port->dst_port;
169
170         err = kernel_bind(vxlan_port->vxlan_rcv_socket, (struct sockaddr *)&sin,
171                           sizeof(struct sockaddr_in));
172         if (err)
173                 goto error_sock;
174
175         udp_sk(vxlan_port->vxlan_rcv_socket->sk)->encap_type = UDP_ENCAP_VXLAN;
176         udp_sk(vxlan_port->vxlan_rcv_socket->sk)->encap_rcv = vxlan_rcv;
177
178         udp_encap_enable();
179
180         return 0;
181
182 error_sock:
183         sk_release_kernel(vxlan_port->vxlan_rcv_socket->sk);
184 error:
185         pr_warn("cannot register vxlan protocol handler\n");
186         return err;
187 }
188
189 static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb)
190 {
191         struct vxlan_port *vxlan_port = vxlan_vport(vport);
192
193         if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, ntohs(vxlan_port->dst_port)))
194                 return -EMSGSIZE;
195         return 0;
196 }
197
198 static void vxlan_tnl_destroy(struct vport *vport)
199 {
200         struct vxlan_port *vxlan_port = vxlan_vport(vport);
201
202         list_del_rcu(&vxlan_port->list);
203         /* Release socket */
204         sk_release_kernel(vxlan_port->vxlan_rcv_socket->sk);
205
206         ovs_vport_deferred_free(vport);
207 }
208
209 static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
210 {
211         struct net *net = ovs_dp_get_net(parms->dp);
212         struct nlattr *options = parms->options;
213         struct vxlan_port *vxlan_port;
214         struct vport *vport;
215         struct nlattr *a;
216         int err;
217         u16 dst_port;
218
219         if (!options) {
220                 err = -EINVAL;
221                 goto error;
222         }
223         a = nla_find_nested(options, OVS_TUNNEL_ATTR_DST_PORT);
224         if (a && nla_len(a) == sizeof(u16)) {
225                 dst_port = nla_get_u16(a);
226         } else {
227                 /* Require destination port from userspace. */
228                 err = -EINVAL;
229                 goto error;
230         }
231
232         /* Verify if we already have a socket created for this port */
233         if (vxlan_find_port(net, htons(dst_port))) {
234                 err = -EEXIST;
235                 goto error;
236         }
237
238         vport = ovs_vport_alloc(sizeof(struct vxlan_port),
239                                 &ovs_vxlan_vport_ops, parms);
240         if (IS_ERR(vport))
241                 return vport;
242
243         vxlan_port = vxlan_vport(vport);
244         vxlan_port->dst_port = htons(dst_port);
245         strncpy(vxlan_port->name, parms->name, IFNAMSIZ);
246
247         err = vxlan_socket_init(vxlan_port, net);
248         if (err)
249                 goto error_free;
250
251         list_add_tail_rcu(&vxlan_port->list, &vxlan_ports);
252         return vport;
253
254 error_free:
255         ovs_vport_free(vport);
256 error:
257         return ERR_PTR(err);
258 }
259
260 static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
261 {
262         if (unlikely(!OVS_CB(skb)->tun_key)) {
263                 ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
264                 kfree_skb(skb);
265                 return 0;
266         }
267
268         return ovs_tnl_send(vport, skb, IPPROTO_UDP,
269                         VXLAN_HLEN, vxlan_build_header);
270 }
271
272 static const char *vxlan_get_name(const struct vport *vport)
273 {
274         struct vxlan_port *vxlan_port = vxlan_vport(vport);
275         return vxlan_port->name;
276 }
277
278 const struct vport_ops ovs_vxlan_vport_ops = {
279         .type           = OVS_VPORT_TYPE_VXLAN,
280         .flags          = VPORT_F_TUN_ID,
281         .create         = vxlan_tnl_create,
282         .destroy        = vxlan_tnl_destroy,
283         .get_name       = vxlan_get_name,
284         .get_options    = vxlan_get_options,
285         .send           = vxlan_tnl_send,
286 };
287 #else
288 #warning VXLAN tunneling will not be available on kernels before 2.6.26
289 #endif /* Linux kernel < 2.6.26 */