tap: refactor packets handling functions
Consolidate pool_tap4() and pool_tap6() into tap_flush_pools(), and tap4_handler() and tap6_handler() into tap_handler(). Create a generic tap_add_packet() to consolidate packet addition logic and reduce code duplication. The purpose is to ease the export of these functions to use them with the vhost-user backend. Signed-off-by: Laurent Vivier <lvivier@redhat.com> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
fba2b544b6
commit
9ecf7fedc5
2 changed files with 64 additions and 49 deletions
110
tap.c
110
tap.c
|
@ -921,6 +921,58 @@ append:
|
||||||
return in->count;
|
return in->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tap_flush_pools() - Flush both IPv4 and IPv6 packet pools
|
||||||
|
*/
|
||||||
|
void tap_flush_pools(void)
|
||||||
|
{
|
||||||
|
pool_flush(pool_tap4);
|
||||||
|
pool_flush(pool_tap6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tap_handler() - IPv4/IPv6 and ARP packet handler for tap file descriptor
|
||||||
|
* @c: Execution context
|
||||||
|
* @now: Current timestamp
|
||||||
|
*/
|
||||||
|
void tap_handler(struct ctx *c, const struct timespec *now)
|
||||||
|
{
|
||||||
|
tap4_handler(c, pool_tap4, now);
|
||||||
|
tap6_handler(c, pool_tap6, now);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tap_add_packet() - Queue/capture packet, update notion of guest MAC address
|
||||||
|
* @c: Execution context
|
||||||
|
* @l2len: Total L2 packet length
|
||||||
|
* @p: Packet buffer
|
||||||
|
*/
|
||||||
|
void tap_add_packet(struct ctx *c, ssize_t l2len, char *p)
|
||||||
|
{
|
||||||
|
const struct ethhdr *eh;
|
||||||
|
|
||||||
|
pcap(p, l2len);
|
||||||
|
|
||||||
|
eh = (struct ethhdr *)p;
|
||||||
|
|
||||||
|
if (memcmp(c->mac_guest, eh->h_source, ETH_ALEN)) {
|
||||||
|
memcpy(c->mac_guest, eh->h_source, ETH_ALEN);
|
||||||
|
proto_update_l2_buf(c->mac_guest, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ntohs(eh->h_proto)) {
|
||||||
|
case ETH_P_ARP:
|
||||||
|
case ETH_P_IP:
|
||||||
|
packet_add(pool_tap4, l2len, p);
|
||||||
|
break;
|
||||||
|
case ETH_P_IPV6:
|
||||||
|
packet_add(pool_tap6, l2len, p);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tap_sock_reset() - Handle closing or failure of connect AF_UNIX socket
|
* tap_sock_reset() - Handle closing or failure of connect AF_UNIX socket
|
||||||
* @c: Execution context
|
* @c: Execution context
|
||||||
|
@ -947,7 +999,6 @@ static void tap_sock_reset(struct ctx *c)
|
||||||
void tap_handler_passt(struct ctx *c, uint32_t events,
|
void tap_handler_passt(struct ctx *c, uint32_t events,
|
||||||
const struct timespec *now)
|
const struct timespec *now)
|
||||||
{
|
{
|
||||||
const struct ethhdr *eh;
|
|
||||||
ssize_t n, rem;
|
ssize_t n, rem;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
|
@ -960,8 +1011,7 @@ redo:
|
||||||
p = pkt_buf;
|
p = pkt_buf;
|
||||||
rem = 0;
|
rem = 0;
|
||||||
|
|
||||||
pool_flush(pool_tap4);
|
tap_flush_pools();
|
||||||
pool_flush(pool_tap6);
|
|
||||||
|
|
||||||
n = recv(c->fd_tap, p, TAP_BUF_FILL, MSG_DONTWAIT);
|
n = recv(c->fd_tap, p, TAP_BUF_FILL, MSG_DONTWAIT);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
|
@ -988,38 +1038,18 @@ redo:
|
||||||
/* Complete the partial read above before discarding a malformed
|
/* Complete the partial read above before discarding a malformed
|
||||||
* frame, otherwise the stream will be inconsistent.
|
* frame, otherwise the stream will be inconsistent.
|
||||||
*/
|
*/
|
||||||
if (l2len < (ssize_t)sizeof(*eh) ||
|
if (l2len < (ssize_t)sizeof(struct ethhdr) ||
|
||||||
l2len > (ssize_t)ETH_MAX_MTU)
|
l2len > (ssize_t)ETH_MAX_MTU)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
pcap(p, l2len);
|
tap_add_packet(c, l2len, p);
|
||||||
|
|
||||||
eh = (struct ethhdr *)p;
|
|
||||||
|
|
||||||
if (memcmp(c->mac_guest, eh->h_source, ETH_ALEN)) {
|
|
||||||
memcpy(c->mac_guest, eh->h_source, ETH_ALEN);
|
|
||||||
proto_update_l2_buf(c->mac_guest, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ntohs(eh->h_proto)) {
|
|
||||||
case ETH_P_ARP:
|
|
||||||
case ETH_P_IP:
|
|
||||||
packet_add(pool_tap4, l2len, p);
|
|
||||||
break;
|
|
||||||
case ETH_P_IPV6:
|
|
||||||
packet_add(pool_tap6, l2len, p);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
next:
|
next:
|
||||||
p += l2len;
|
p += l2len;
|
||||||
n -= l2len;
|
n -= l2len;
|
||||||
}
|
}
|
||||||
|
|
||||||
tap4_handler(c, pool_tap4, now);
|
tap_handler(c, now);
|
||||||
tap6_handler(c, pool_tap6, now);
|
|
||||||
|
|
||||||
/* We can't use EPOLLET otherwise. */
|
/* We can't use EPOLLET otherwise. */
|
||||||
if (rem)
|
if (rem)
|
||||||
|
@ -1044,35 +1074,18 @@ void tap_handler_pasta(struct ctx *c, uint32_t events,
|
||||||
redo:
|
redo:
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
pool_flush(pool_tap4);
|
tap_flush_pools();
|
||||||
pool_flush(pool_tap6);
|
|
||||||
restart:
|
restart:
|
||||||
while ((len = read(c->fd_tap, pkt_buf + n, TAP_BUF_BYTES - n)) > 0) {
|
while ((len = read(c->fd_tap, pkt_buf + n, TAP_BUF_BYTES - n)) > 0) {
|
||||||
const struct ethhdr *eh = (struct ethhdr *)(pkt_buf + n);
|
|
||||||
|
|
||||||
if (len < (ssize_t)sizeof(*eh) || len > (ssize_t)ETH_MAX_MTU) {
|
if (len < (ssize_t)sizeof(struct ethhdr) ||
|
||||||
|
len > (ssize_t)ETH_MAX_MTU) {
|
||||||
n += len;
|
n += len;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pcap(pkt_buf + n, len);
|
|
||||||
|
|
||||||
if (memcmp(c->mac_guest, eh->h_source, ETH_ALEN)) {
|
tap_add_packet(c, len, pkt_buf + n);
|
||||||
memcpy(c->mac_guest, eh->h_source, ETH_ALEN);
|
|
||||||
proto_update_l2_buf(c->mac_guest, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ntohs(eh->h_proto)) {
|
|
||||||
case ETH_P_ARP:
|
|
||||||
case ETH_P_IP:
|
|
||||||
packet_add(pool_tap4, len, pkt_buf + n);
|
|
||||||
break;
|
|
||||||
case ETH_P_IPV6:
|
|
||||||
packet_add(pool_tap6, len, pkt_buf + n);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((n += len) == TAP_BUF_BYTES)
|
if ((n += len) == TAP_BUF_BYTES)
|
||||||
break;
|
break;
|
||||||
|
@ -1083,8 +1096,7 @@ restart:
|
||||||
|
|
||||||
ret = errno;
|
ret = errno;
|
||||||
|
|
||||||
tap4_handler(c, pool_tap4, now);
|
tap_handler(c, now);
|
||||||
tap6_handler(c, pool_tap6, now);
|
|
||||||
|
|
||||||
if (len > 0 || ret == EAGAIN)
|
if (len > 0 || ret == EAGAIN)
|
||||||
return;
|
return;
|
||||||
|
|
3
tap.h
3
tap.h
|
@ -70,5 +70,8 @@ void tap_handler_passt(struct ctx *c, uint32_t events,
|
||||||
const struct timespec *now);
|
const struct timespec *now);
|
||||||
int tap_sock_unix_open(char *sock_path);
|
int tap_sock_unix_open(char *sock_path);
|
||||||
void tap_sock_init(struct ctx *c);
|
void tap_sock_init(struct ctx *c);
|
||||||
|
void tap_flush_pools(void);
|
||||||
|
void tap_handler(struct ctx *c, const struct timespec *now);
|
||||||
|
void tap_add_packet(struct ctx *c, ssize_t l2len, char *p);
|
||||||
|
|
||||||
#endif /* TAP_H */
|
#endif /* TAP_H */
|
||||||
|
|
Loading…
Reference in a new issue