2 * VDE - vde_vxlan Network emulator for vde
3 * Copyright (C) 2014 Renzo Davoli, Alessandro Ghedini VirtualSquare
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include <netinet/in.h>
28 #include "vxlan_hash.h"
33 #define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
34 #define hton24(p, v) { \
35 p[0] = (((v) >> 16) & 0xFF); \
36 p[1] = (((v) >> 8) & 0xFF); \
37 p[2] = ((v) & 0xFF); \
41 in_addr_t vxlan_addr
= INADDR_NONE
;
42 int vxlan_port
= 4879;
45 static int vxlan_fd
= -1;
47 void vxlan_open(struct pollfd
*pfd
) {
51 struct ip_mreq mc_req
;
52 struct sockaddr_in addr_in
;
54 if ((sock
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0) {
55 printlog(LOG_ERR
, "socket(): %s", strerror(errno
));
59 if ((setsockopt(sock
, IPPROTO_IP
, IP_MULTICAST_TTL
,
60 &vxlan_mttl
, sizeof(vxlan_mttl
))) < 0) {
61 printlog(LOG_ERR
, "setsockopt(TTL): %s", strerror(errno
));
65 if ((setsockopt(sock
, IPPROTO_IP
, IP_MULTICAST_LOOP
,
66 &loop
, sizeof(loop
))) < 0) {
67 printlog(LOG_ERR
, "setsockopt(LOOP): %s", strerror(errno
));
71 memset(&addr_in
, 0, sizeof(addr_in
));
72 addr_in
.sin_family
= AF_INET
;
73 addr_in
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
74 addr_in
.sin_port
= htons(vxlan_port
);
76 if ((bind(sock
, (struct sockaddr
*) &addr_in
, sizeof(addr_in
))) < 0) {
77 printlog(LOG_ERR
, "bind(): %s", strerror(errno
));
81 /* send an IGMP join request */
82 mc_req
.imr_multiaddr
.s_addr
= vxlan_addr
;
83 mc_req
.imr_interface
.s_addr
= htonl(INADDR_ANY
);
85 if ((setsockopt(sock
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
86 &mc_req
, sizeof(mc_req
))) < 0) {
87 printlog(LOG_ERR
, "setsockopt(ADD): %s", strerror(errno
));
94 pfd
[2].events
= POLLIN
| POLLHUP
;
97 void vxlan_process() {
100 struct sockaddr_in src_addr
;
101 socklen_t src_addr_len
=sizeof(src_addr
);
105 size_t len
= recvfrom(vxlan_fd
, &pkt
, sizeof(pkt
), 0,
106 (struct sockaddr
*) &src_addr
, &src_addr_len
);
109 printlog(LOG_ERR
, "recvfrom(): %s", strerror(errno
));
111 printlog(LOG_DEBUG
, "VXLAN packet from %s",inet_ntoa(src_addr
.sin_addr
));
113 if (pkt
.flags
!= (1<<3)) {
114 printlog(LOG_ERR
, "Invalid flags");
118 if (ntoh24(pkt
.id
) != vxlan_id
) {
119 printlog(LOG_DEBUG
, "Invalid VNI");
123 find_in_hash_update(pkt
.pkt
.header
.src
, vxlan_id
,
124 src_addr
.sin_addr
.s_addr
, NULL
);
126 if ((pkt
.pkt
.header
.dest
[0] == 0xff) &&
127 (pkt
.pkt
.header
.dest
[1] == 0xff) &&
128 (pkt
.pkt
.header
.dest
[2] == 0xff) &&
129 (pkt
.pkt
.header
.dest
[3] == 0xff) &&
130 (pkt
.pkt
.header
.dest
[4] == 0xff) &&
131 (pkt
.pkt
.header
.dest
[5] == 0xff)) {
132 printlog(LOG_DEBUG
, "Broadcast send");
134 plug_send(&pkt
.pkt
, len
-offsetof(struct vxlan_pkt
,pkt
));
138 find_in_hash(pkt
.pkt
.header
.dest
, vxlan_id
, &dest_addr
);
142 printlog(LOG_DEBUG
, "Not found");
144 plug_send(&pkt
.pkt
,len
-offsetof(struct vxlan_pkt
,pkt
));
145 printlog(LOG_DEBUG
, "Send to VDE");
149 printlog(LOG_DEBUG
, "Drop");
154 void vxlan_send(in_addr_t addr_s
, struct vxlan_pkt
*pkt
, size_t len
) {
155 struct sockaddr_in addr
;
157 addr
.sin_family
= AF_INET
;
158 addr
.sin_addr
.s_addr
= addr_s
? addr_s
: vxlan_addr
;
159 addr
.sin_port
= htons(vxlan_port
);
161 memset(pkt
, 0, offsetof(struct vxlan_pkt
,pkt
));
162 pkt
->flags
= (1 << 3);
164 hton24(pkt
->id
, vxlan_id
);
166 if (sendto(vxlan_fd
, pkt
, len
+offsetof(struct vxlan_pkt
,pkt
), 0,
167 (struct sockaddr
*) &addr
, sizeof(addr
)) < 0)
168 printlog(LOG_ERR
, "sendto(): %s", strerror(errno
));
175 struct ip_mreq mc_req
;
177 mc_req
.imr_multiaddr
.s_addr
= vxlan_addr
;
178 mc_req
.imr_interface
.s_addr
= htonl(INADDR_ANY
);
180 if ((setsockopt(vxlan_fd
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
,
181 (void *) &mc_req
, sizeof(mc_req
))) < 0) {
182 printlog(LOG_ERR
, "setsockopt(DROP): %s", strerror(errno
));