2 * Copyright (c) 2011 Nicira, Inc.
3 * Copyright (c) 2012 Cisco Systems, Inc.
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.
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.
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
20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22 #include <linux/version.h>
23 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
27 #include <linux/net.h>
28 #include <linux/rculist.h>
29 #include <linux/udp.h>
39 #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
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.
51 #define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
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.
62 struct list_head list
;
63 struct socket
*vxlan_rcv_socket
;
67 static LIST_HEAD(vxlan_ports
);
69 static inline struct vxlan_port
*vxlan_vport(const struct vport
*vport
)
71 return vport_priv(vport
);
74 static struct vxlan_port
*vxlan_find_port(struct net
*net
, __be16 port
)
76 struct vxlan_port
*vxlan_port
;
78 list_for_each_entry_rcu(vxlan_port
, &vxlan_ports
, list
) {
80 if (vxlan_port
->dst_port
== port
&&
81 net_eq(sock_net(vxlan_port
->vxlan_rcv_socket
->sk
), net
))
88 static inline struct vxlanhdr
*vxlan_hdr(const struct sk_buff
*skb
)
90 return (struct vxlanhdr
*)(udp_hdr(skb
) + 1);
93 static void vxlan_build_header(const struct vport
*vport
,
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
;
102 udph
->dest
= vxlan_port
->dst_port
;
103 udph
->source
= htons(ovs_tnl_get_src_port(skb
));
105 udph
->len
= htons(skb
->len
- skb_transport_offset(skb
));
107 vxh
->vx_flags
= htonl(VXLAN_FLAGS
);
108 vxh
->vx_vni
= htonl(be64_to_cpu(tun_key
->tun_id
) << 8);
111 /* Called with rcu_read_lock and BH disabled. */
112 static int vxlan_rcv(struct sock
*sk
, struct sk_buff
*skb
)
114 struct vxlan_port
*vxlan_vport
;
115 struct vxlanhdr
*vxh
;
117 struct ovs_key_ipv4_tunnel tun_key
;
120 vxlan_vport
= vxlan_find_port(dev_net(skb
->dev
), udp_hdr(skb
)->dest
);
121 if (unlikely(!vxlan_vport
))
124 if (unlikely(!pskb_may_pull(skb
, VXLAN_HLEN
+ ETH_HLEN
)))
127 vxh
= vxlan_hdr(skb
);
128 if (unlikely(vxh
->vx_flags
!= htonl(VXLAN_FLAGS
) ||
129 vxh
->vx_vni
& htonl(0xff)))
132 skb_pull_rcsum(skb
, VXLAN_HLEN
);
134 key
= cpu_to_be64(ntohl(vxh
->vx_vni
) >> 8);
136 /* Save outer tunnel values */
138 tnl_tun_key_init(&tun_key
, iph
, key
, OVS_TNL_F_KEY
);
140 ovs_tnl_rcv(vport_from_priv(vxlan_vport
), skb
, &tun_key
);
149 /* Random value. Irrelevant as long as it's not 0 since we set the handler. */
150 #define UDP_ENCAP_VXLAN 1
151 static int vxlan_socket_init(struct vxlan_port
*vxlan_port
, struct net
*net
)
153 struct sockaddr_in sin
;
156 err
= sock_create_kern(AF_INET
, SOCK_DGRAM
, 0,
157 &vxlan_port
->vxlan_rcv_socket
);
161 /* release net ref. */
162 sk_change_net(vxlan_port
->vxlan_rcv_socket
->sk
, net
);
164 sin
.sin_family
= AF_INET
;
165 sin
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
166 sin
.sin_port
= vxlan_port
->dst_port
;
168 err
= kernel_bind(vxlan_port
->vxlan_rcv_socket
, (struct sockaddr
*)&sin
,
169 sizeof(struct sockaddr_in
));
173 udp_sk(vxlan_port
->vxlan_rcv_socket
->sk
)->encap_type
= UDP_ENCAP_VXLAN
;
174 udp_sk(vxlan_port
->vxlan_rcv_socket
->sk
)->encap_rcv
= vxlan_rcv
;
181 sk_release_kernel(vxlan_port
->vxlan_rcv_socket
->sk
);
183 pr_warn("cannot register vxlan protocol handler\n");
187 static int vxlan_get_options(const struct vport
*vport
, struct sk_buff
*skb
)
189 struct vxlan_port
*vxlan_port
= vxlan_vport(vport
);
191 if (nla_put_u16(skb
, OVS_TUNNEL_ATTR_DST_PORT
, ntohs(vxlan_port
->dst_port
)))
196 static void vxlan_tnl_destroy(struct vport
*vport
)
198 struct vxlan_port
*vxlan_port
= vxlan_vport(vport
);
200 list_del_rcu(&vxlan_port
->list
);
202 sk_release_kernel(vxlan_port
->vxlan_rcv_socket
->sk
);
204 ovs_vport_deferred_free(vport
);
207 static struct vport
*vxlan_tnl_create(const struct vport_parms
*parms
)
209 struct net
*net
= ovs_dp_get_net(parms
->dp
);
210 struct nlattr
*options
= parms
->options
;
211 struct vxlan_port
*vxlan_port
;
221 a
= nla_find_nested(options
, OVS_TUNNEL_ATTR_DST_PORT
);
222 if (a
&& nla_len(a
) == sizeof(u16
)) {
223 dst_port
= nla_get_u16(a
);
225 /* Require destination port from userspace. */
230 /* Verify if we already have a socket created for this port */
231 if (vxlan_find_port(net
, htons(dst_port
))) {
236 vport
= ovs_vport_alloc(sizeof(struct vxlan_port
),
237 &ovs_vxlan_vport_ops
, parms
);
241 vxlan_port
= vxlan_vport(vport
);
242 vxlan_port
->dst_port
= htons(dst_port
);
243 strncpy(vxlan_port
->name
, parms
->name
, IFNAMSIZ
);
245 err
= vxlan_socket_init(vxlan_port
, net
);
249 list_add_tail_rcu(&vxlan_port
->list
, &vxlan_ports
);
253 ovs_vport_free(vport
);
258 static int vxlan_tnl_send(struct vport
*vport
, struct sk_buff
*skb
)
260 if (unlikely(!OVS_CB(skb
)->tun_key
))
263 return ovs_tnl_send(vport
, skb
, IPPROTO_UDP
,
264 VXLAN_HLEN
, vxlan_build_header
);
267 static const char *vxlan_get_name(const struct vport
*vport
)
269 struct vxlan_port
*vxlan_port
= vxlan_vport(vport
);
270 return vxlan_port
->name
;
273 const struct vport_ops ovs_vxlan_vport_ops
= {
274 .type
= OVS_VPORT_TYPE_VXLAN
,
275 .create
= vxlan_tnl_create
,
276 .destroy
= vxlan_tnl_destroy
,
277 .get_name
= vxlan_get_name
,
278 .get_options
= vxlan_get_options
,
279 .send
= vxlan_tnl_send
,
282 #warning VXLAN tunneling will not be available on kernels before 2.6.26
283 #endif /* Linux kernel < 2.6.26 */