3 #include <linux/virtio_net.h>
4 #include <linux/kernel.h>
5 #include <linux/list.h>
6 #include <sys/socket.h>
10 #define UIP_UDP_MAX_EVENTS 1000
12 static struct uip_udp_socket
*uip_udp_socket_find(struct uip_tx_arg
*arg
, u32 sip
, u32 dip
, u16 sport
, u16 dport
)
14 struct list_head
*sk_head
;
15 struct uip_udp_socket
*sk
;
16 pthread_mutex_t
*sk_lock
;
17 struct epoll_event ev
;
21 sk_head
= &arg
->info
->udp_socket_head
;
22 sk_lock
= &arg
->info
->udp_socket_lock
;
28 list_for_each_entry(sk
, sk_head
, list
) {
29 if (sk
->sip
== sip
&& sk
->dip
== dip
&& sk
->sport
== sport
&& sk
->dport
== dport
) {
30 mutex_unlock(sk_lock
);
34 mutex_unlock(sk_lock
);
39 sk
= malloc(sizeof(*sk
));
40 memset(sk
, 0, sizeof(*sk
));
44 sk
->fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
51 flags
= fcntl(sk
->fd
, F_GETFL
, 0);
53 fcntl(sk
->fd
, F_SETFL
, flags
);
56 * Add sk->fd to epoll_wait
61 if (arg
->info
->udp_epollfd
<= 0)
62 arg
->info
->udp_epollfd
= epoll_create(UIP_UDP_MAX_EVENTS
);
63 ret
= epoll_ctl(arg
->info
->udp_epollfd
, EPOLL_CTL_ADD
, sk
->fd
, &ev
);
65 pr_warning("epoll_ctl error");
67 sk
->addr
.sin_family
= AF_INET
;
68 sk
->addr
.sin_addr
.s_addr
= dip
;
69 sk
->addr
.sin_port
= dport
;
77 list_add_tail(&sk
->list
, sk_head
);
78 mutex_unlock(sk_lock
);
87 static int uip_udp_socket_send(struct uip_udp_socket
*sk
, struct uip_udp
*udp
)
92 len
= ntohs(udp
->len
) - uip_udp_hdrlen(udp
);
94 ret
= sendto(sk
->fd
, udp
->payload
, len
, 0, (struct sockaddr
*)&sk
->addr
, sizeof(sk
->addr
));
101 int uip_udp_make_pkg(struct uip_info
*info
, struct uip_udp_socket
*sk
, struct uip_buf
*buf
, u8
* payload
, int payload_len
)
103 struct uip_eth
*eth2
;
104 struct uip_udp
*udp2
;
108 * Cook a ethernet frame
110 udp2
= (struct uip_udp
*)(buf
->eth
);
111 eth2
= (struct uip_eth
*)buf
->eth
;
112 ip2
= (struct uip_ip
*)(buf
->eth
);
114 eth2
->src
= info
->host_mac
;
115 eth2
->dst
= info
->guest_mac
;
116 eth2
->type
= htons(UIP_ETH_P_IP
);
118 ip2
->vhl
= UIP_IP_VER_4
| UIP_IP_HDR_LEN
;
122 ip2
->ttl
= UIP_IP_TTL
;
123 ip2
->proto
= UIP_IP_P_UDP
;
128 udp2
->sport
= sk
->dport
;
129 udp2
->dport
= sk
->sport
;
131 udp2
->len
= htons(payload_len
+ uip_udp_hdrlen(udp2
));
135 memcpy(udp2
->payload
, payload
, payload_len
);
137 ip2
->len
= udp2
->len
+ htons(uip_ip_hdrlen(ip2
));
138 ip2
->csum
= uip_csum_ip(ip2
);
139 udp2
->csum
= uip_csum_udp(udp2
);
144 buf
->vnet_len
= sizeof(struct virtio_net_hdr
);
145 memset(buf
->vnet
, 0, buf
->vnet_len
);
147 buf
->eth_len
= ntohs(ip2
->len
) + uip_eth_hdrlen(&ip2
->eth
);
152 static void *uip_udp_socket_thread(void *p
)
154 struct epoll_event events
[UIP_UDP_MAX_EVENTS
];
155 struct uip_udp_socket
*sk
;
156 struct uip_info
*info
;
166 payload
= malloc(UIP_MAX_UDP_PAYLOAD
);
170 nfds
= epoll_wait(info
->udp_epollfd
, events
, UIP_UDP_MAX_EVENTS
, -1);
175 for (i
= 0; i
< nfds
; i
++) {
177 sk
= events
[i
].data
.ptr
;
178 payload_len
= recvfrom(sk
->fd
, payload
, UIP_MAX_UDP_PAYLOAD
, 0, NULL
, NULL
);
183 * Get free buffer to send data to guest
185 buf
= uip_buf_get_free(info
);
187 uip_udp_make_pkg(info
, sk
, buf
, payload
, payload_len
);
190 * Send data received from socket to guest
192 uip_buf_set_used(info
, buf
);
201 int uip_tx_do_ipv4_udp(struct uip_tx_arg
*arg
)
203 struct uip_udp_socket
*sk
;
204 struct uip_info
*info
;
209 udp
= (struct uip_udp
*)(arg
->eth
);
210 ip
= (struct uip_ip
*)(arg
->eth
);
213 if (uip_udp_is_dhcp(udp
)) {
214 uip_tx_do_ipv4_udp_dhcp(arg
);
219 * Find socket we have allocated before, otherwise allocate one
221 sk
= uip_udp_socket_find(arg
, ip
->sip
, ip
->dip
, udp
->sport
, udp
->dport
);
226 * Send out UDP data to remote host
228 ret
= uip_udp_socket_send(sk
, udp
);
232 if (!info
->udp_thread
)
233 pthread_create(&info
->udp_thread
, NULL
, uip_udp_socket_thread
, (void *)info
);