lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 10 Nov 2020 20:46:39 +0800
From:   Hangbin Liu <liuhangbin@...il.com>
To:     bpf@...r.kernel.org
Cc:     netdev@...r.kernel.org, Daniel Borkmann <daniel@...earbox.net>,
        Jesper Dangaard Brouer <brouer@...hat.com>,
        John Fastabend <john.fastabend@...il.com>,
        "David S . Miller" <davem@...emloft.net>,
        Toke Høiland-Jørgensen <toke@...hat.com>,
        Tariq Toukan <tariqt@...lanox.com>,
        Hangbin Liu <liuhangbin@...il.com>
Subject: [PATCH bpf-next] samples/bpf: add xdp_redirect_map with xdp_prog support

This patch add running xdp program on egress interface support for
xdp_redirect_map sample. The new prog will change the IP ttl based
on egress ifindex.

Signed-off-by: Hangbin Liu <liuhangbin@...il.com>
---
 samples/bpf/xdp_redirect_map_kern.c | 74 ++++++++++++++++++++++++++++-
 samples/bpf/xdp_redirect_map_user.c | 21 ++++----
 2 files changed, 86 insertions(+), 9 deletions(-)

diff --git a/samples/bpf/xdp_redirect_map_kern.c b/samples/bpf/xdp_redirect_map_kern.c
index 6489352ab7a4..e5ebff2271f4 100644
--- a/samples/bpf/xdp_redirect_map_kern.c
+++ b/samples/bpf/xdp_redirect_map_kern.c
@@ -22,7 +22,7 @@
 struct {
 	__uint(type, BPF_MAP_TYPE_DEVMAP);
 	__uint(key_size, sizeof(int));
-	__uint(value_size, sizeof(int));
+	__uint(value_size, sizeof(struct bpf_devmap_val));
 	__uint(max_entries, 100);
 } tx_port SEC(".maps");
 
@@ -52,6 +52,48 @@ static void swap_src_dst_mac(void *data)
 	p[5] = dst[2];
 }
 
+static __always_inline __u16 csum_fold_helper(__u32 csum)
+{
+	__u32 sum;
+	sum = (csum & 0xffff) + (csum >> 16);
+	sum += (sum >> 16);
+	return ~sum;
+}
+
+static __always_inline __u16 ipv4_csum(__u16 seed, struct iphdr *iphdr_new,
+				       struct iphdr *iphdr_old)
+{
+	__u32 csum, size = sizeof(struct iphdr);
+	csum = bpf_csum_diff((__be32 *)iphdr_old, size,
+			     (__be32 *)iphdr_new, size, seed);
+	return csum_fold_helper(csum);
+}
+
+static void parse_ipv4(void *data, u64 nh_off, void *data_end, u8 ttl)
+{
+	struct iphdr *iph = data + nh_off;
+	struct iphdr iph_old;
+	__u16 csum_old;
+
+	if (iph + 1 > data_end)
+		return;
+
+	iph_old = *iph;
+	csum_old = iph->check;
+	iph->ttl = ttl;
+	iph->check = ipv4_csum(~csum_old, iph, &iph_old);
+}
+
+static void parse_ipv6(void *data, u64 nh_off, void *data_end, u8 hop_limit)
+{
+	struct ipv6hdr *ip6h = data + nh_off;
+
+	if (ip6h + 1 > data_end)
+		return;
+
+	ip6h->hop_limit = hop_limit;
+}
+
 SEC("xdp_redirect_map")
 int xdp_redirect_map_prog(struct xdp_md *ctx)
 {
@@ -82,6 +124,36 @@ int xdp_redirect_map_prog(struct xdp_md *ctx)
 	return bpf_redirect_map(&tx_port, vport, 0);
 }
 
+/* This map prog will set new IP ttl based on egress ifindex */
+SEC("xdp_devmap/map_prog")
+int xdp_devmap_prog(struct xdp_md *ctx)
+{
+	char fmt[] = "devmap redirect: egress dev %u with new ttl %u\n";
+	void *data_end = (void *)(long)ctx->data_end;
+	void *data = (void *)(long)ctx->data;
+	struct ethhdr *eth = data;
+	u16 h_proto;
+	u64 nh_off;
+	u8 ttl;
+
+	nh_off = sizeof(struct ethhdr);
+	if (data + nh_off > data_end)
+		return XDP_DROP;
+
+	/* set new ttl based on egress ifindex */
+	ttl = ctx->egress_ifindex % 64;
+
+	h_proto = eth->h_proto;
+	if (h_proto == htons(ETH_P_IP))
+		parse_ipv4(data, nh_off, data_end, ttl);
+	else if (h_proto == htons(ETH_P_IPV6))
+		parse_ipv6(data, nh_off, data_end, ttl);
+
+	bpf_trace_printk(fmt, sizeof(fmt), ctx->egress_ifindex, ttl);
+
+	return XDP_PASS;
+}
+
 /* Redirect require an XDP bpf_prog loaded on the TX device */
 SEC("xdp_redirect_dummy")
 int xdp_redirect_dummy_prog(struct xdp_md *ctx)
diff --git a/samples/bpf/xdp_redirect_map_user.c b/samples/bpf/xdp_redirect_map_user.c
index 35e16dee613e..9a95eab629bd 100644
--- a/samples/bpf/xdp_redirect_map_user.c
+++ b/samples/bpf/xdp_redirect_map_user.c
@@ -98,12 +98,13 @@ int main(int argc, char **argv)
 {
 	struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
 	struct bpf_prog_load_attr prog_load_attr = {
-		.prog_type	= BPF_PROG_TYPE_XDP,
+		.prog_type	= BPF_PROG_TYPE_UNSPEC,
 	};
-	struct bpf_program *prog, *dummy_prog;
+	struct bpf_program *prog, *dummy_prog, *devmap_prog;
+	int prog_fd, dummy_prog_fd, devmap_prog_fd;
+	struct bpf_devmap_val devmap_val;
 	struct bpf_prog_info info = {};
 	__u32 info_len = sizeof(info);
-	int prog_fd, dummy_prog_fd;
 	const char *optstr = "FSN";
 	struct bpf_object *obj;
 	int ret, opt, key = 0;
@@ -157,16 +158,18 @@ int main(int argc, char **argv)
 		return 1;
 
 	prog = bpf_program__next(NULL, obj);
-	dummy_prog = bpf_program__next(prog, obj);
-	if (!prog || !dummy_prog) {
+	devmap_prog = bpf_object__find_program_by_title(obj, "xdp_devmap/map_prog");
+	dummy_prog = bpf_object__find_program_by_title(obj, "xdp_redirect_dummy");
+	if (!prog || !devmap_prog || !dummy_prog) {
 		printf("finding a prog in obj file failed\n");
 		return 1;
 	}
 	/* bpf_prog_load_xattr gives us the pointer to first prog's fd,
-	 * so we're missing only the fd for dummy prog
+	 * so we're missing the fd for devmap and dummy prog
 	 */
+	devmap_prog_fd = bpf_program__fd(devmap_prog);
 	dummy_prog_fd = bpf_program__fd(dummy_prog);
-	if (prog_fd < 0 || dummy_prog_fd < 0) {
+	if (prog_fd < 0 || devmap_prog_fd < 0 || dummy_prog_fd < 0) {
 		printf("bpf_prog_load_xattr: %s\n", strerror(errno));
 		return 1;
 	}
@@ -209,7 +212,9 @@ int main(int argc, char **argv)
 	signal(SIGTERM, int_exit);
 
 	/* populate virtual to physical port map */
-	ret = bpf_map_update_elem(tx_port_map_fd, &key, &ifindex_out, 0);
+	devmap_val.bpf_prog.fd = devmap_prog_fd;
+	devmap_val.ifindex = ifindex_out;
+	ret = bpf_map_update_elem(tx_port_map_fd, &key, &devmap_val, 0);
 	if (ret) {
 		perror("bpf_update_elem");
 		goto out;
-- 
2.25.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ