Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Check if we can migrate child sockets.
  4 *
  5 *   1. If reuse_md->migrating_sk is NULL (SYN packet),
  6 *        return SK_PASS without selecting a listener.
  7 *   2. If reuse_md->migrating_sk is not NULL (socket migration),
  8 *        select a listener (reuseport_map[migrate_map[cookie]])
  9 *
 10 * Author: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
 11 */
 12
 13#include <stddef.h>
 14#include <string.h>
 15#include <linux/bpf.h>
 16#include <linux/if_ether.h>
 17#include <linux/ip.h>
 18#include <linux/ipv6.h>
 19#include <linux/tcp.h>
 20#include <linux/in.h>
 21#include <bpf/bpf_endian.h>
 22#include <bpf/bpf_helpers.h>
 23
 24struct {
 25	__uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
 26	__uint(max_entries, 256);
 27	__type(key, int);
 28	__type(value, __u64);
 29} reuseport_map SEC(".maps");
 30
 31struct {
 32	__uint(type, BPF_MAP_TYPE_HASH);
 33	__uint(max_entries, 256);
 34	__type(key, __u64);
 35	__type(value, int);
 36} migrate_map SEC(".maps");
 37
 38int migrated_at_close = 0;
 39int migrated_at_close_fastopen = 0;
 40int migrated_at_send_synack = 0;
 41int migrated_at_recv_ack = 0;
 42__be16 server_port;
 43
 44SEC("xdp")
 45int drop_ack(struct xdp_md *xdp)
 46{
 47	void *data_end = (void *)(long)xdp->data_end;
 48	void *data = (void *)(long)xdp->data;
 49	struct ethhdr *eth = data;
 50	struct tcphdr *tcp = NULL;
 51
 52	if (eth + 1 > data_end)
 53		goto pass;
 54
 55	switch (bpf_ntohs(eth->h_proto)) {
 56	case ETH_P_IP: {
 57		struct iphdr *ip = (struct iphdr *)(eth + 1);
 58
 59		if (ip + 1 > data_end)
 60			goto pass;
 61
 62		if (ip->protocol != IPPROTO_TCP)
 63			goto pass;
 64
 65		tcp = (struct tcphdr *)((void *)ip + ip->ihl * 4);
 66		break;
 67	}
 68	case ETH_P_IPV6: {
 69		struct ipv6hdr *ipv6 = (struct ipv6hdr *)(eth + 1);
 70
 71		if (ipv6 + 1 > data_end)
 72			goto pass;
 73
 74		if (ipv6->nexthdr != IPPROTO_TCP)
 75			goto pass;
 76
 77		tcp = (struct tcphdr *)(ipv6 + 1);
 78		break;
 79	}
 80	default:
 81		goto pass;
 82	}
 83
 84	if (tcp + 1 > data_end)
 85		goto pass;
 86
 87	if (tcp->dest != server_port)
 88		goto pass;
 89
 90	if (!tcp->syn && tcp->ack)
 91		return XDP_DROP;
 92
 93pass:
 94	return XDP_PASS;
 95}
 96
 97SEC("sk_reuseport/migrate")
 98int migrate_reuseport(struct sk_reuseport_md *reuse_md)
 99{
100	int *key, flags = 0, state, err;
101	__u64 cookie;
102
103	if (!reuse_md->migrating_sk)
104		return SK_PASS;
105
106	state = reuse_md->migrating_sk->state;
107	cookie = bpf_get_socket_cookie(reuse_md->sk);
108
109	key = bpf_map_lookup_elem(&migrate_map, &cookie);
110	if (!key)
111		return SK_DROP;
112
113	err = bpf_sk_select_reuseport(reuse_md, &reuseport_map, key, flags);
114	if (err)
115		return SK_PASS;
116
117	switch (state) {
118	case BPF_TCP_ESTABLISHED:
119		__sync_fetch_and_add(&migrated_at_close, 1);
120		break;
121	case BPF_TCP_SYN_RECV:
122		__sync_fetch_and_add(&migrated_at_close_fastopen, 1);
123		break;
124	case BPF_TCP_NEW_SYN_RECV:
125		if (!reuse_md->len)
126			__sync_fetch_and_add(&migrated_at_send_synack, 1);
127		else
128			__sync_fetch_and_add(&migrated_at_recv_ack, 1);
129		break;
130	}
131
132	return SK_PASS;
133}
134
135char _license[] SEC("license") = "GPL";
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Check if we can migrate child sockets.
  4 *
  5 *   1. If reuse_md->migrating_sk is NULL (SYN packet),
  6 *        return SK_PASS without selecting a listener.
  7 *   2. If reuse_md->migrating_sk is not NULL (socket migration),
  8 *        select a listener (reuseport_map[migrate_map[cookie]])
  9 *
 10 * Author: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
 11 */
 12
 13#include <stddef.h>
 14#include <string.h>
 15#include <linux/bpf.h>
 16#include <linux/if_ether.h>
 17#include <linux/ip.h>
 18#include <linux/ipv6.h>
 19#include <linux/tcp.h>
 20#include <linux/in.h>
 21#include <bpf/bpf_endian.h>
 22#include <bpf/bpf_helpers.h>
 23
 24struct {
 25	__uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
 26	__uint(max_entries, 256);
 27	__type(key, int);
 28	__type(value, __u64);
 29} reuseport_map SEC(".maps");
 30
 31struct {
 32	__uint(type, BPF_MAP_TYPE_HASH);
 33	__uint(max_entries, 256);
 34	__type(key, __u64);
 35	__type(value, int);
 36} migrate_map SEC(".maps");
 37
 38int migrated_at_close = 0;
 39int migrated_at_close_fastopen = 0;
 40int migrated_at_send_synack = 0;
 41int migrated_at_recv_ack = 0;
 42__be16 server_port;
 43
 44SEC("xdp")
 45int drop_ack(struct xdp_md *xdp)
 46{
 47	void *data_end = (void *)(long)xdp->data_end;
 48	void *data = (void *)(long)xdp->data;
 49	struct ethhdr *eth = data;
 50	struct tcphdr *tcp = NULL;
 51
 52	if (eth + 1 > data_end)
 53		goto pass;
 54
 55	switch (bpf_ntohs(eth->h_proto)) {
 56	case ETH_P_IP: {
 57		struct iphdr *ip = (struct iphdr *)(eth + 1);
 58
 59		if (ip + 1 > data_end)
 60			goto pass;
 61
 62		if (ip->protocol != IPPROTO_TCP)
 63			goto pass;
 64
 65		tcp = (struct tcphdr *)((void *)ip + ip->ihl * 4);
 66		break;
 67	}
 68	case ETH_P_IPV6: {
 69		struct ipv6hdr *ipv6 = (struct ipv6hdr *)(eth + 1);
 70
 71		if (ipv6 + 1 > data_end)
 72			goto pass;
 73
 74		if (ipv6->nexthdr != IPPROTO_TCP)
 75			goto pass;
 76
 77		tcp = (struct tcphdr *)(ipv6 + 1);
 78		break;
 79	}
 80	default:
 81		goto pass;
 82	}
 83
 84	if (tcp + 1 > data_end)
 85		goto pass;
 86
 87	if (tcp->dest != server_port)
 88		goto pass;
 89
 90	if (!tcp->syn && tcp->ack)
 91		return XDP_DROP;
 92
 93pass:
 94	return XDP_PASS;
 95}
 96
 97SEC("sk_reuseport/migrate")
 98int migrate_reuseport(struct sk_reuseport_md *reuse_md)
 99{
100	int *key, flags = 0, state, err;
101	__u64 cookie;
102
103	if (!reuse_md->migrating_sk)
104		return SK_PASS;
105
106	state = reuse_md->migrating_sk->state;
107	cookie = bpf_get_socket_cookie(reuse_md->sk);
108
109	key = bpf_map_lookup_elem(&migrate_map, &cookie);
110	if (!key)
111		return SK_DROP;
112
113	err = bpf_sk_select_reuseport(reuse_md, &reuseport_map, key, flags);
114	if (err)
115		return SK_PASS;
116
117	switch (state) {
118	case BPF_TCP_ESTABLISHED:
119		__sync_fetch_and_add(&migrated_at_close, 1);
120		break;
121	case BPF_TCP_SYN_RECV:
122		__sync_fetch_and_add(&migrated_at_close_fastopen, 1);
123		break;
124	case BPF_TCP_NEW_SYN_RECV:
125		if (!reuse_md->len)
126			__sync_fetch_and_add(&migrated_at_send_synack, 1);
127		else
128			__sync_fetch_and_add(&migrated_at_recv_ack, 1);
129		break;
130	}
131
132	return SK_PASS;
133}
134
135char _license[] SEC("license") = "GPL";