udp: Use the same buffer for the L2 header for all frames
Currently each tap-bound frame buffer has room for its own ethernet header. However the ethernet header is always the same for such frames, so now that we're indirectly referencing the ethernet header via iov, we can use a single buffer for all of them. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
parent
6170688616
commit
d4598e1d18
1 changed files with 15 additions and 21 deletions
36
udp.c
36
udp.c
|
@ -186,39 +186,40 @@ static struct udp_payload_t {
|
||||||
#endif
|
#endif
|
||||||
udp_payload[UDP_MAX_FRAMES];
|
udp_payload[UDP_MAX_FRAMES];
|
||||||
|
|
||||||
|
/* Ethernet header for IPv4 frames */
|
||||||
|
static struct ethhdr udp4_eth_hdr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* udp4_l2_buf_t - Pre-cooked IPv4 packet buffers for tap connections
|
* udp4_l2_buf_t - Pre-cooked IPv4 packet buffers for tap connections
|
||||||
* @s_in: Source socket address, filled in by recvmmsg()
|
* @s_in: Source socket address, filled in by recvmmsg()
|
||||||
* @taph: Tap backend specific header
|
* @taph: Tap backend specific header
|
||||||
* @eh: Prefilled ethernet header
|
|
||||||
* @iph: Pre-filled IP header (except for tot_len and saddr)
|
* @iph: Pre-filled IP header (except for tot_len and saddr)
|
||||||
*/
|
*/
|
||||||
static struct udp4_l2_buf_t {
|
static struct udp4_l2_buf_t {
|
||||||
struct sockaddr_in s_in;
|
struct sockaddr_in s_in;
|
||||||
|
|
||||||
struct tap_hdr taph;
|
struct tap_hdr taph;
|
||||||
struct ethhdr eh;
|
|
||||||
struct iphdr iph;
|
struct iphdr iph;
|
||||||
} __attribute__ ((packed, aligned(__alignof__(unsigned int))))
|
} __attribute__ ((packed, aligned(__alignof__(unsigned int))))
|
||||||
udp4_l2_buf[UDP_MAX_FRAMES];
|
udp4_l2_buf[UDP_MAX_FRAMES];
|
||||||
|
|
||||||
|
/* Ethernet header for IPv6 frames */
|
||||||
|
static struct ethhdr udp6_eth_hdr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* udp6_l2_buf_t - Pre-cooked IPv6 packet buffers for tap connections
|
* udp6_l2_buf_t - Pre-cooked IPv6 packet buffers for tap connections
|
||||||
* @s_in6: Source socket address, filled in by recvmmsg()
|
* @s_in6: Source socket address, filled in by recvmmsg()
|
||||||
* @taph: Tap backend specific header
|
* @taph: Tap backend specific header
|
||||||
* @eh: Pre-filled ethernet header
|
|
||||||
* @ip6h: Pre-filled IP header (except for payload_len and addresses)
|
* @ip6h: Pre-filled IP header (except for payload_len and addresses)
|
||||||
*/
|
*/
|
||||||
struct udp6_l2_buf_t {
|
struct udp6_l2_buf_t {
|
||||||
struct sockaddr_in6 s_in6;
|
struct sockaddr_in6 s_in6;
|
||||||
#ifdef __AVX2__
|
#ifdef __AVX2__
|
||||||
/* Align ip6h to 32-byte boundary. */
|
/* Align ip6h to 32-byte boundary. */
|
||||||
uint8_t pad[64 - (sizeof(struct sockaddr_in6) + sizeof(struct ethhdr) +
|
uint8_t pad[64 - (sizeof(struct sockaddr_in6) + sizeof(struct tap_hdr))];
|
||||||
sizeof(struct tap_hdr))];
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct tap_hdr taph;
|
struct tap_hdr taph;
|
||||||
struct ethhdr eh;
|
|
||||||
struct ipv6hdr ip6h;
|
struct ipv6hdr ip6h;
|
||||||
#ifdef __AVX2__
|
#ifdef __AVX2__
|
||||||
} __attribute__ ((packed, aligned(32)))
|
} __attribute__ ((packed, aligned(32)))
|
||||||
|
@ -307,15 +308,8 @@ static void udp_invert_portmap(struct udp_fwd_ports *fwd)
|
||||||
*/
|
*/
|
||||||
void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s)
|
void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s)
|
||||||
{
|
{
|
||||||
int i;
|
eth_update_mac(&udp4_eth_hdr, eth_d, eth_s);
|
||||||
|
eth_update_mac(&udp6_eth_hdr, eth_d, eth_s);
|
||||||
for (i = 0; i < UDP_MAX_FRAMES; i++) {
|
|
||||||
struct udp4_l2_buf_t *b4 = &udp4_l2_buf[i];
|
|
||||||
struct udp6_l2_buf_t *b6 = &udp6_l2_buf[i];
|
|
||||||
|
|
||||||
eth_update_mac(&b4->eh, eth_d, eth_s);
|
|
||||||
eth_update_mac(&b6->eh, eth_d, eth_s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -329,6 +323,8 @@ static void udp_iov_init_one(const struct ctx *c, size_t i)
|
||||||
struct iovec *siov = &udp_l2_iov_sock[i];
|
struct iovec *siov = &udp_l2_iov_sock[i];
|
||||||
|
|
||||||
*siov = IOV_OF_LVALUE(payload->data);
|
*siov = IOV_OF_LVALUE(payload->data);
|
||||||
|
udp4_eth_hdr.h_proto = htons_constant(ETH_P_IP);
|
||||||
|
udp6_eth_hdr.h_proto = htons_constant(ETH_P_IPV6);
|
||||||
|
|
||||||
if (c->ifi4) {
|
if (c->ifi4) {
|
||||||
struct msghdr *mh = &udp4_l2_mh_sock[i].msg_hdr;
|
struct msghdr *mh = &udp4_l2_mh_sock[i].msg_hdr;
|
||||||
|
@ -336,7 +332,6 @@ static void udp_iov_init_one(const struct ctx *c, size_t i)
|
||||||
struct iovec *tiov = udp4_l2_iov_tap[i];
|
struct iovec *tiov = udp4_l2_iov_tap[i];
|
||||||
|
|
||||||
*buf = (struct udp4_l2_buf_t) {
|
*buf = (struct udp4_l2_buf_t) {
|
||||||
.eh = ETH_HDR_INIT(ETH_P_IP),
|
|
||||||
.iph = L2_BUF_IP4_INIT(IPPROTO_UDP)
|
.iph = L2_BUF_IP4_INIT(IPPROTO_UDP)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -346,7 +341,7 @@ static void udp_iov_init_one(const struct ctx *c, size_t i)
|
||||||
mh->msg_iovlen = 1;
|
mh->msg_iovlen = 1;
|
||||||
|
|
||||||
tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &buf->taph);
|
tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &buf->taph);
|
||||||
tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(buf->eh);
|
tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp4_eth_hdr);
|
||||||
tiov[UDP_IOV_IP] = IOV_OF_LVALUE(buf->iph);
|
tiov[UDP_IOV_IP] = IOV_OF_LVALUE(buf->iph);
|
||||||
tiov[UDP_IOV_PAYLOAD].iov_base = payload;
|
tiov[UDP_IOV_PAYLOAD].iov_base = payload;
|
||||||
}
|
}
|
||||||
|
@ -357,7 +352,6 @@ static void udp_iov_init_one(const struct ctx *c, size_t i)
|
||||||
struct iovec *tiov = udp6_l2_iov_tap[i];
|
struct iovec *tiov = udp6_l2_iov_tap[i];
|
||||||
|
|
||||||
*buf = (struct udp6_l2_buf_t) {
|
*buf = (struct udp6_l2_buf_t) {
|
||||||
.eh = ETH_HDR_INIT(ETH_P_IPV6),
|
|
||||||
.ip6h = L2_BUF_IP6_INIT(IPPROTO_UDP)
|
.ip6h = L2_BUF_IP6_INIT(IPPROTO_UDP)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -367,7 +361,7 @@ static void udp_iov_init_one(const struct ctx *c, size_t i)
|
||||||
mh->msg_iovlen = 1;
|
mh->msg_iovlen = 1;
|
||||||
|
|
||||||
tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &buf->taph);
|
tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &buf->taph);
|
||||||
tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(buf->eh);
|
tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp6_eth_hdr);
|
||||||
tiov[UDP_IOV_IP] = IOV_OF_LVALUE(buf->ip6h);
|
tiov[UDP_IOV_IP] = IOV_OF_LVALUE(buf->ip6h);
|
||||||
tiov[UDP_IOV_PAYLOAD].iov_base = payload;
|
tiov[UDP_IOV_PAYLOAD].iov_base = payload;
|
||||||
}
|
}
|
||||||
|
@ -631,7 +625,7 @@ static size_t udp_update_hdr4(const struct ctx *c, struct udp4_l2_buf_t *bh,
|
||||||
bp->uh.len = htons(l4len);
|
bp->uh.len = htons(l4len);
|
||||||
csum_udp4(&bp->uh, src, dst, bp->data, dlen);
|
csum_udp4(&bp->uh, src, dst, bp->data, dlen);
|
||||||
|
|
||||||
tap_hdr_update(&bh->taph, l3len + sizeof(bh->eh));
|
tap_hdr_update(&bh->taph, l3len + sizeof(udp4_eth_hdr));
|
||||||
return l4len;
|
return l4len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,7 +696,7 @@ static size_t udp_update_hdr6(const struct ctx *c, struct udp6_l2_buf_t *bh,
|
||||||
bp->uh.len = bh->ip6h.payload_len;
|
bp->uh.len = bh->ip6h.payload_len;
|
||||||
csum_udp6(&bp->uh, src, dst, bp->data, dlen);
|
csum_udp6(&bp->uh, src, dst, bp->data, dlen);
|
||||||
|
|
||||||
tap_hdr_update(&bh->taph, l4len + sizeof(bh->ip6h) + sizeof(bh->eh));
|
tap_hdr_update(&bh->taph, l4len + sizeof(bh->ip6h) + sizeof(udp6_eth_hdr));
|
||||||
return l4len;
|
return l4len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue