mirror of
https://passt.top/passt
synced 2025-06-14 11:35:33 +02:00

To allow more batching, we group together related packets into "seqs" in the tap layer, before passing them to the L4 protocol layers. Currently we consider the IP protocol, both IP addresses and also the L4 ports when grouping things into seqs. We ignore the IPv6 flow label. We have some future cases where we want to consider the the flow label in the L4 code, which is awkward if we could be given a single batch with multiple labels. Add the flow label to tap6_l4_t and group by it as well as the other criteria. In future we could possibly use the flow label _instead_ of peeking into the L4 header for the ports, but we don't do so for now. The guest should use the same flow label for all packets in a low, but if it doesn't this change won't break anything, it just means we'll batch things a bit sub-optimally. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
131 lines
3.5 KiB
C
131 lines
3.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright (c) 2021 Red Hat GmbH
|
|
* Author: Stefano Brivio <sbrivio@redhat.com>
|
|
*/
|
|
|
|
#ifndef IP_H
|
|
#define IP_H
|
|
|
|
#include <netinet/ip.h>
|
|
#include <netinet/ip6.h>
|
|
|
|
#define IN4_IS_ADDR_UNSPECIFIED(a) \
|
|
(((struct in_addr *)(a))->s_addr == htonl_constant(INADDR_ANY))
|
|
#define IN4_IS_ADDR_BROADCAST(a) \
|
|
(((struct in_addr *)(a))->s_addr == htonl_constant(INADDR_BROADCAST))
|
|
#define IN4_IS_ADDR_LOOPBACK(a) \
|
|
(ntohl(((struct in_addr *)(a))->s_addr) >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET)
|
|
#define IN4_IS_ADDR_MULTICAST(a) \
|
|
(IN_MULTICAST(ntohl(((struct in_addr *)(a))->s_addr)))
|
|
#define IN4_ARE_ADDR_EQUAL(a, b) \
|
|
(((struct in_addr *)(a))->s_addr == ((struct in_addr *)b)->s_addr)
|
|
#define IN4ADDR_LOOPBACK_INIT \
|
|
{ .s_addr = htonl_constant(INADDR_LOOPBACK) }
|
|
#define IN4ADDR_ANY_INIT \
|
|
{ .s_addr = htonl_constant(INADDR_ANY) }
|
|
|
|
#define IN4_IS_ADDR_LINKLOCAL(a) \
|
|
((ntohl(((struct in_addr *)(a))->s_addr) >> 16) == 0xa9fe)
|
|
#define IN4_IS_PREFIX_LINKLOCAL(a, len) \
|
|
((len) >= 16 && IN4_IS_ADDR_LINKLOCAL(a))
|
|
|
|
#define L2_BUF_IP4_INIT(proto) \
|
|
{ \
|
|
.version = 4, \
|
|
.ihl = 5, \
|
|
.tos = 0, \
|
|
.tot_len = 0, \
|
|
.id = 0, \
|
|
.frag_off = 0, \
|
|
.ttl = 0xff, \
|
|
.protocol = (proto), \
|
|
.saddr = 0, \
|
|
.daddr = 0, \
|
|
}
|
|
#define L2_BUF_IP4_PSUM(proto) ((uint32_t)htons_constant(0x4500) + \
|
|
(uint32_t)htons(0xff00 | (proto)))
|
|
|
|
|
|
#define IN6_IS_PREFIX_LINKLOCAL(a, len) \
|
|
((len) >= 10 && IN6_IS_ADDR_LINKLOCAL(a))
|
|
|
|
#define L2_BUF_IP6_INIT(proto) \
|
|
{ \
|
|
.priority = 0, \
|
|
.version = 6, \
|
|
.flow_lbl = { 0 }, \
|
|
.payload_len = 0, \
|
|
.nexthdr = (proto), \
|
|
.hop_limit = 255, \
|
|
.saddr = IN6ADDR_ANY_INIT, \
|
|
.daddr = IN6ADDR_ANY_INIT, \
|
|
}
|
|
|
|
struct ipv6hdr {
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wpedantic"
|
|
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
uint8_t version:4,
|
|
priority:4;
|
|
#else
|
|
uint8_t priority:4,
|
|
version:4;
|
|
#endif
|
|
#pragma GCC diagnostic pop
|
|
uint8_t flow_lbl[3];
|
|
|
|
uint16_t payload_len;
|
|
uint8_t nexthdr;
|
|
uint8_t hop_limit;
|
|
|
|
struct in6_addr saddr;
|
|
struct in6_addr daddr;
|
|
};
|
|
|
|
struct ipv6_opt_hdr {
|
|
uint8_t nexthdr;
|
|
uint8_t hdrlen;
|
|
/*
|
|
* TLV encoded option data follows.
|
|
*/
|
|
} __attribute__((packed)); /* required for some archs */
|
|
|
|
/**
|
|
* ip6_set_flow_lbl() - Set flow label in an IPv6 header
|
|
* @ip6h: Pointer to IPv6 header, updated
|
|
* @flow: Set @ip6h flow label to the low 20 bits of this integer
|
|
*/
|
|
static inline void ip6_set_flow_lbl(struct ipv6hdr *ip6h, uint32_t flow)
|
|
{
|
|
ip6h->flow_lbl[0] = (flow >> 16) & 0xf;
|
|
ip6h->flow_lbl[1] = (flow >> 8) & 0xff;
|
|
ip6h->flow_lbl[2] = (flow >> 0) & 0xff;
|
|
}
|
|
|
|
/** ip6_get_flow_lbl() - Get flow label from an IPv6 header
|
|
* @ip6h: Pointer to IPv6 header
|
|
*
|
|
* Return: flow label from @ip6h as an integer (<= 20 bits)
|
|
*/
|
|
static inline uint32_t ip6_get_flow_lbl(const struct ipv6hdr *ip6h)
|
|
{
|
|
return (ip6h->flow_lbl[0] & 0xf) << 16 |
|
|
ip6h->flow_lbl[1] << 8 |
|
|
ip6h->flow_lbl[2];
|
|
}
|
|
|
|
char *ipv6_l4hdr(const struct pool *p, int idx, size_t offset, uint8_t *proto,
|
|
size_t *dlen);
|
|
|
|
/* IPv6 link-local all-nodes multicast adddress, ff02::1 */
|
|
static const struct in6_addr in6addr_ll_all_nodes = {
|
|
.s6_addr = {
|
|
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
|
},
|
|
};
|
|
|
|
/* IPv4 Limited Broadcast (RFC 919, Section 7), 255.255.255.255 */
|
|
static const struct in_addr in4addr_broadcast = { 0xffffffff };
|
|
|
|
#endif /* IP_H */
|