当前位置: 首页 > wzjs >正文

宁波百度做网站的公司哪家好上海企业优化

宁波百度做网站的公司哪家好,上海企业优化,外贸独立网站seo,税务网站建设的基本要求上周验证了ebpf/xdp的一些功能,具体是对端打流灌包,然后本端网卡在网卡驱动层会检测是否是具体的数据包类型(udp),还有是否符合端口号(port)等,其它不符合规则的包一律交给linux内核…

上周验证了ebpf/xdp的一些功能,具体是对端打流灌包,然后本端网卡在网卡驱动层会检测是否是具体的数据包类型(udp),还有是否符合端口号(port)等,其它不符合规则的包一律交给linux内核协议栈进行处理。想要验证这个功能的话,需要有两台机器,内核版本最好是v6.6(因为我的是,之前5.10版本的时候老是遇到奇奇怪怪的问题,要么缺这要么缺那,而且本身也是离线状态,又是比较稀缺的欧拉系统,找起资源来比较困难,buff叠满于是索性把内核版本升级到6.6,后面基本上没遇到什么问题)我用的是欧拉系统,为了匹配内核版本,我把eulerOS也升级到了24.03LTS。

项目文件的话就一内核态程序和一用户态程序,方便编译也有提供makefile(也可以自己用clang,gcc编译),也包括xdpload程序。其它文件还好,xdploader是可执行程序,不好贴在这里,可以自己上网上找找看能不能找到,也可以去我的csdn资源库下载

内核态程序,复制命名为af_xdp_kern.c

/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/if_link.h>
#include <linux/if_ether.h>
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <netinet/udp.h>
struct {__uint(type, BPF_MAP_TYPE_XSKMAP);__type(key, __u32);__type(value, __u32);__uint(max_entries, 64);
} xsks_map SEC(".maps");struct {__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);__type(key, __u32);__type(value, __u32);__uint(max_entries, 64);
} xdp_stats_map SEC(".maps");SEC("xdp")
int xdp_sock_prog(struct xdp_md *ctx)
{int index = ctx->rx_queue_index;__u32 *pkt_count;void *data_end = (void *)(long)ctx->data_end;void *data = (void *)(long)ctx->data;struct ethhdr *eth = data;if (eth + 1 > data_end ) return XDP_PASS;if (eth->h_proto != htons(ETH_P_IPV6))return XDP_PASS;struct ipv6hdr *ip6h = (struct ipv6hdr *)(eth + 1);if (ip6h + 1 > data_end) return XDP_PASS;if (ip6h->nexthdr != IPPROTO_UDP)return XDP_PASS;struct udphdr *udp = (struct udphdr *)(ip6h +1);if (udp + 1 > data_end) return XDP_PASS;if (udp->dest != htons(8805))return XDP_PASS;pkt_count = bpf_map_lookup_elem(&xdp_stats_map, &index);if (pkt_count) {// We pass every other packet //if ((*pkt_count)++ & 1)//return XDP_PASS;bpf_printk("packet type = udp ipv6");}/* A set entry here means that the correspnding queue_id* has an active AF_XDP socket bound to it. */if (bpf_map_lookup_elem(&xsks_map, &index))bpf_printk("goto the bpf_redirect_map function");return bpf_redirect_map(&xsks_map, index, 0);return XDP_PASS;
}char _license[] SEC("license") = "GPL";

用户态程序 命名为af_xdp_user.c (代码比较长)

/* SPDX-License-Identifier: GPL-2.0 */#include <assert.h>
#include <errno.h>
#include <getopt.h>
#include <locale.h>
#include <poll.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <string.h>#include <sys/resource.h>#include <bpf/bpf.h>
#include <xdp/xsk.h>
#include <xdp/libxdp.h>#include <arpa/inet.h>
#include <net/if.h>
#include <linux/if_link.h>
#include <linux/if_ether.h>
#include <linux/ipv6.h>#include <linux/icmpv6.h>
#include <netinet/udp.h>#include "../common/common_params.h"
#include "../common/common_user_bpf_xdp.h"
#include "../common/common_libbpf.h"#define NUM_FRAMES         4096
#define FRAME_SIZE         XSK_UMEM__DEFAULT_FRAME_SIZE
#define RX_BATCH_SIZE      64
#define INVALID_UMEM_FRAME UINT64_MAXstatic struct xdp_program *prog;
int xsk_map_fd;
bool custom_xsk = false;
struct config cfg = {.ifindex   = -1,
};struct xsk_umem_info {struct xsk_ring_prod fq;struct xsk_ring_cons cq;struct xsk_umem *umem;void *buffer;
};
struct stats_record {uint64_t timestamp;uint64_t rx_packets;uint64_t rx_bytes;uint64_t tx_packets;uint64_t tx_bytes;
};
struct xsk_socket_info {struct xsk_ring_cons rx;struct xsk_ring_prod tx;struct xsk_umem_info *umem;struct xsk_socket *xsk;uint64_t umem_frame_addr[NUM_FRAMES];uint32_t umem_frame_free;uint32_t outstanding_tx;struct stats_record stats;struct stats_record prev_stats;
};struct dummyheader{struct in6_addr src;struct in6_addr dst;uint32_t len;uint8_t zero[3];uint8_t next_hdr;
}; static inline __u32 xsk_ring_prod__free(struct xsk_ring_prod *r)
{r->cached_cons = *r->consumer + r->size;return r->cached_cons - r->cached_prod;
}static const char *__doc__ = "AF_XDP kernel bypass example\n";static const struct option_wrapper long_options[] = {{{"help",	 no_argument,		NULL, 'h' },"Show help", NULL, false},{{"dev",	 required_argument,	NULL, 'd' },"Operate on device <ifname>", "<ifname>", true},{{"skb-mode",	 no_argument,		NULL, 'S' },"Install XDP program in SKB (AKA generic) mode",NULL,false},{{"native-mode", no_argument,		NULL, 'N' },"Install XDP program in native mode",NULL,false},{{"auto-mode",	 no_argument,		NULL, 'A' },"Auto-detect SKB or native mode",NULL,false},{{"force",	 no_argument,		NULL, 'F' },"Force install, replacing existing program on interface",NULL,false},{{"copy",        no_argument,		NULL, 'c' },"Force copy mode",NULL,false},{{"zero-copy",	 no_argument,		NULL, 'z' },"Force zero-copy mode",NULL,false},{{"queue",	 required_argument,	NULL, 'Q' },"Configure interface receive queue for AF_XDP, default=0",NULL,false},{{"poll-mode",	 no_argument,		NULL, 'p' },"Use the poll() API waiting for packets to arrive",NULL,false},{{"quiet",	 no_argument,		NULL, 'q' },"Quiet mode (no output)",NULL,false},{{"filename",    required_argument,	NULL,  1  },"Load program from <file>", "<file>",false},{{"progname",	 required_argument,	NULL,  2  },"Load program from function <name> in the ELF file", "<name>",false},{{0, 0, NULL,  0 }, "0", NULL, false}
};static bool global_exit;static struct xsk_umem_info *configure_xsk_umem(void *buffer, uint64_t size)
{struct xsk_umem_info *umem;int ret;umem = calloc(1, sizeof(*umem));if (!umem)return NULL;ret = xsk_umem__create(&umem->umem, buffer, size, &umem->fq, &umem->cq,NULL);if (ret) {errno = -ret;return NULL;}umem->buffer = buffer;return umem;
}static uint64_t xsk_alloc_umem_frame(struct xsk_socket_info *xsk)
{uint64_t frame;if (xsk->umem_frame_free == 0)return INVALID_UMEM_FRAME;frame = xsk->umem_frame_addr[--xsk->umem_frame_free];xsk->umem_frame_addr[xsk->umem_frame_free] = INVALID_UMEM_FRAME;return frame;
}static void xsk_free_umem_frame(struct xsk_socket_info *xsk, uint64_t frame)
{assert(xsk->umem_frame_free < NUM_FRAMES);xsk->umem_frame_addr[xsk->umem_frame_free++] = frame;
}static uint64_t xsk_umem_free_frames(struct xsk_socket_info *xsk)
{return xsk->umem_frame_free;
}static struct xsk_socket_info *xsk_configure_socket(struct config *cfg,struct xsk_umem_info *umem)
{struct xsk_socket_config xsk_cfg;struct xsk_socket_info *xsk_info;uint32_t idx;unsigned int i;unsigned int ret;uint32_t prog_id;xsk_info = calloc(1, sizeof(*xsk_info));if (!xsk_info)return NULL;xsk_info->umem = umem;xsk_cfg.rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS;xsk_cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS;xsk_cfg.xdp_flags = cfg->xdp_flags;xsk_cfg.bind_flags = cfg->xsk_bind_flags;xsk_cfg.libbpf_flags = (custom_xsk) ? XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD: 0;ret = xsk_socket__create(&xsk_info->xsk, cfg->ifname,cfg->xsk_if_queue, umem->umem, &xsk_info->rx,&xsk_info->tx, &xsk_cfg);if (ret)goto error_exit;if (custom_xsk) {ret = xsk_socket__update_xskmap(xsk_info->xsk, xsk_map_fd);if (ret)goto error_exit;} else {/* Getting the program ID must be after the xdp_socket__create() call */if (bpf_xdp_query_id(cfg->ifindex, cfg->xdp_flags, &prog_id))goto error_exit;}/* Initialize umem frame allocation */for (i = 0; i < NUM_FRAMES; i++)xsk_info->umem_frame_addr[i] = i * FRAME_SIZE;xsk_info->umem_frame_free = NUM_FRAMES;/* Stuff the receive path with buffers, we assume we have enough */ret = xsk_ring_prod__reserve(&xsk_info->umem->fq,XSK_RING_PROD__DEFAULT_NUM_DESCS,&idx);if (ret != XSK_RING_PROD__DEFAULT_NUM_DESCS)goto error_exit;for (i = 0; i < XSK_RING_PROD__DEFAULT_NUM_DESCS; i ++)*xsk_ring_prod__fill_addr(&xsk_info->umem->fq, idx++) =xsk_alloc_umem_frame(xsk_info);xsk_ring_prod__submit(&xsk_info->umem->fq,XSK_RING_PROD__DEFAULT_NUM_DESCS);return xsk_info;error_exit:errno = -ret;return NULL;
}static void complete_tx(struct xsk_socket_info *xsk)
{unsigned int completed;uint32_t idx_cq;if (!xsk->outstanding_tx)return;sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);/* Collect/free completed TX buffers */completed = xsk_ring_cons__peek(&xsk->umem->cq,XSK_RING_CONS__DEFAULT_NUM_DESCS,&idx_cq);if (completed > 0) {for (unsigned int i = 0; i < completed; i++)xsk_free_umem_frame(xsk,*xsk_ring_cons__comp_addr(&xsk->umem->cq,idx_cq++));xsk_ring_cons__release(&xsk->umem->cq, completed);xsk->outstanding_tx -= completed < xsk->outstanding_tx ?completed : xsk->outstanding_tx;}
}static inline __sum16 csum16_add(__sum16 csum, __be16 addend)
{uint16_t res = (uint16_t)csum;res += (__u16)addend;return (__sum16)(res + (res < (__u16)addend));
}static inline __sum16 csum16_sub(__sum16 csum, __be16 addend)
{return csum16_add(csum, ~addend);
}static inline void csum_replace2(__sum16 *sum, __be16 old, __be16 new)
{*sum = ~csum16_add(csum16_sub(~(*sum), old), new);
}static uint16_t udp6_checksum(struct ipv6hdr *ipv6, struct udphdr *udp) {// 伪头部结构(需按网络字节序填充)struct dummyheader pseudo_header;uint32_t total_len = ntohs(udp->len);uint32_t csum = 0;uint16_t *ptr;// 填充伪头部memcpy(&pseudo_header.src, &ipv6->saddr, sizeof(pseudo_header.src));memcpy(&pseudo_header.dst, &ipv6->daddr, sizeof(pseudo_header.dst));pseudo_header.len = htonl(total_len);memset(pseudo_header.zero, 0, 3);pseudo_header.next_hdr = IPPROTO_UDP;// 计算伪头部校验和ptr = (uint16_t*)&pseudo_header;for (unsigned int i = 0; i < sizeof(pseudo_header)/2; i++) {csum += ntohs(ptr[i]);}// 计算UDP头校验和ptr = (uint16_t*)udp;for (unsigned int i = 0; i < sizeof(*udp)/2; i++) {csum += ntohs(ptr[i]);}// 计算payload校验和(需要处理奇数长度)uint8_t *payload = (uint8_t*)(udp + 1);int payload_len = total_len - sizeof(*udp);for (int i = 0; i < payload_len/2; i++) {csum += ntohs(((uint16_t*)payload)[i]);}if (payload_len % 2) {csum += (payload[payload_len-1] << 8);}// 折叠进位并取反while (csum >> 16)csum = (csum & 0xffff) + (csum >> 16);return ~csum;
}static void check_error(struct ethhdr *eth, struct ipv6hdr *ipv6, struct udphdr *udp, uint32_t len)
{//int dest_port = 8805;if (ntohs(eth->h_proto) != ETH_P_IPV6){printf("ERROR: ntohs(eth->h_proto) != ETH_P_IPV6 | expected: %d | actual: %d\n", ETH_P_IPV6, ntohs(eth->h_proto));}if (len < (sizeof(*eth) + sizeof(*ipv6) + sizeof(*udp))){printf("ERROR: len < (sizeof(*eth) + sizeof(*ipv6) + sizeof(*udp))\n");}if (ipv6->nexthdr != IPPROTO_UDP){printf("ERROR: ipv6->nexthdr != IPPROTO_UDP | expected: %d | actual : %d\n", ipv6->nexthdr, IPPROTO_UDP);}//if (ntohs(udp->dest) != 8805){
//	    printf("ERROR: ntohs(udp->dest) != 8805 | expected: %d | actual: %d\n", ntohs(udp->dest),dest_port);
//    }
}static bool process_packet(struct xsk_socket_info *xsk,uint64_t addr, uint32_t len) 
{uint8_t *pkt = xsk_umem__get_data(xsk->umem->buffer, addr);int ret;uint32_t tx_idx = 0;struct ethhdr *eth = (struct ethhdr *)pkt;struct ipv6hdr *ipv6 = (struct ipv6hdr*)(eth + 1);struct udphdr *udp = (struct udphdr*)(ipv6 + 1);// 基本长度校验if (ntohs(eth->h_proto) != ETH_P_IPV6 ||len < (sizeof(*eth) + sizeof(*ipv6) + sizeof(*udp)) ||ipv6->nexthdr != IPPROTO_UDP){//      ntohs(udp->dest) != 8805) {printf("===========packet checkout failed!!!============\n");check_error(eth, ipv6, udp, len);return false;}/* 交换MAC地址 */uint8_t tmp_mac[ETH_ALEN];memcpy(tmp_mac, eth->h_dest, ETH_ALEN);memcpy(eth->h_dest, eth->h_source, ETH_ALEN);memcpy(eth->h_source, tmp_mac, ETH_ALEN);/* 交换IPv6地址 */struct in6_addr tmp_ip;memcpy(&tmp_ip, &ipv6->saddr, sizeof(tmp_ip));memcpy(&ipv6->saddr, &ipv6->daddr, sizeof(tmp_ip));memcpy(&ipv6->daddr, &tmp_ip, sizeof(tmp_ip));/* 交换UDP端口 */uint16_t tmp_port = udp->source;udp->source = udp->dest;  // 原目标端口变为源端口udp->dest = tmp_port;     // 原源端口变为目标端口/* 更新UDP校验和 */udp->check = 0;udp->check = udp6_checksum(ipv6, udp);/* 发送响应包 */ret = xsk_ring_prod__reserve(&xsk->tx, 1, &tx_idx);if (ret != 1) {return false;}xsk_ring_prod__tx_desc(&xsk->tx, tx_idx)->addr = addr;xsk_ring_prod__tx_desc(&xsk->tx, tx_idx)->len = len;xsk_ring_prod__submit(&xsk->tx, 1);xsk->outstanding_tx++;xsk->stats.tx_bytes += len;xsk->stats.tx_packets++;return true;
}static void handle_receive_packets(struct xsk_socket_info *xsk)
{unsigned int rcvd, stock_frames, i;uint32_t idx_rx = 0, idx_fq = 0;unsigned int ret;rcvd = xsk_ring_cons__peek(&xsk->rx, RX_BATCH_SIZE, &idx_rx);if (!rcvd)return;/* Stuff the ring with as much frames as possible */stock_frames = xsk_prod_nb_free(&xsk->umem->fq,xsk_umem_free_frames(xsk));if (stock_frames > 0) {ret = xsk_ring_prod__reserve(&xsk->umem->fq, stock_frames,&idx_fq);/* This should not happen, but just in case */while (ret != stock_frames)ret = xsk_ring_prod__reserve(&xsk->umem->fq, rcvd,&idx_fq);for (i = 0; i < stock_frames; i++)*xsk_ring_prod__fill_addr(&xsk->umem->fq, idx_fq++) =xsk_alloc_umem_frame(xsk);xsk_ring_prod__submit(&xsk->umem->fq, stock_frames);}/* Process received packets */for (i = 0; i < rcvd; i++) {uint64_t addr = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx)->addr;uint32_t len = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx++)->len;if (!process_packet(xsk, addr, len))xsk_free_umem_frame(xsk, addr);xsk->stats.rx_bytes += len;}xsk_ring_cons__release(&xsk->rx, rcvd);xsk->stats.rx_packets += rcvd;/* Do we need to wake up the kernel for transmission */complete_tx(xsk);}static void rx_and_process(struct config *cfg,struct xsk_socket_info *xsk_socket)
{struct pollfd fds[2];int ret, nfds = 1;memset(fds, 0, sizeof(fds));fds[0].fd = xsk_socket__fd(xsk_socket->xsk);fds[0].events = POLLIN;while(!global_exit) {if (cfg->xsk_poll_mode) {ret = poll(fds, nfds, -1);if (ret <= 0 || ret > 1)continue;}handle_receive_packets(xsk_socket);}
}#define NANOSEC_PER_SEC 1000000000 /* 10^9 */
static uint64_t gettime(void)
{struct timespec t;int res;res = clock_gettime(CLOCK_MONOTONIC, &t);if (res < 0) {fprintf(stderr, "Error with gettimeofday! (%i)\n", res);exit(EXIT_FAIL);}return (uint64_t) t.tv_sec * NANOSEC_PER_SEC + t.tv_nsec;
}static double calc_period(struct stats_record *r, struct stats_record *p)
{double period_ = 0;__u64 period = 0;period = r->timestamp - p->timestamp;if (period > 0)period_ = ((double) period / NANOSEC_PER_SEC);return period_;
}static void stats_print(struct stats_record *stats_rec,struct stats_record *stats_prev)
{uint64_t packets, bytes;double period;double pps; /* packets per sec */double bps; /* bits per sec */char *fmt = "%-12s %'11lld pkts (%'10.0f pps)"" %'11lld Kbytes (%'6.0f Mbits/s)"" period:%f\n";period = calc_period(stats_rec, stats_prev);if (period == 0)period = 1;packets = stats_rec->rx_packets - stats_prev->rx_packets;pps     = packets / period;bytes   = stats_rec->rx_bytes   - stats_prev->rx_bytes;bps     = (bytes * 8) / period / 1000000;printf(fmt, "AF_XDP RX:", stats_rec->rx_packets, pps,stats_rec->rx_bytes / 1000 , bps,period);packets = stats_rec->tx_packets - stats_prev->tx_packets;pps     = packets / period;bytes   = stats_rec->tx_bytes   - stats_prev->tx_bytes;bps     = (bytes * 8) / period / 1000000;printf(fmt, "       TX:", stats_rec->tx_packets, pps,stats_rec->tx_bytes / 1000 , bps,period);printf("\n");
}static void *stats_poll(void *arg)
{unsigned int interval = 2;struct xsk_socket_info *xsk = arg;static struct stats_record previous_stats = { 0 };previous_stats.timestamp = gettime();/* Trick to pretty printf with thousands separators use %' */setlocale(LC_NUMERIC, "en_US");while (!global_exit) {sleep(interval);xsk->stats.timestamp = gettime();stats_print(&xsk->stats, &previous_stats);previous_stats = xsk->stats;}return NULL;
}static void exit_application(int signal)
{int err;cfg.unload_all = true;err = do_unload(&cfg);if (err) {fprintf(stderr, "Couldn't detach XDP program on iface '%s' : (%d)\n",cfg.ifname, err);}signal = signal;global_exit = true;
}int main(int argc, char **argv)
{int ret;void *packet_buffer;uint64_t packet_buffer_size;DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);DECLARE_LIBXDP_OPTS(xdp_program_opts, xdp_opts, 0);struct rlimit rlim = {RLIM_INFINITY, RLIM_INFINITY};struct xsk_umem_info *umem;struct xsk_socket_info *xsk_socket;pthread_t stats_poll_thread;int err;char errmsg[1024];/* Global shutdown handler */signal(SIGINT, exit_application);/* Cmdline options can change progname */parse_cmdline_args(argc, argv, long_options, &cfg, __doc__);/* Required option */if (cfg.ifindex == -1) {fprintf(stderr, "ERROR: Required option --dev missing\n\n");usage(argv[0], __doc__, long_options, (argc == 1));return EXIT_FAIL_OPTION;}/* Load custom program if configured */if (cfg.filename[0] != 0) {struct bpf_map *map;custom_xsk = true;xdp_opts.open_filename = cfg.filename;xdp_opts.prog_name = cfg.progname;xdp_opts.opts = &opts;if (cfg.progname[0] != 0) {xdp_opts.open_filename = cfg.filename;xdp_opts.prog_name = cfg.progname;xdp_opts.opts = &opts;prog = xdp_program__create(&xdp_opts);} else {prog = xdp_program__open_file(cfg.filename,NULL, &opts);}err = libxdp_get_error(prog);if (err) {libxdp_strerror(err, errmsg, sizeof(errmsg));fprintf(stderr, "ERR: loading program: %s\n", errmsg);return err;}err = xdp_program__attach(prog, cfg.ifindex, cfg.attach_mode, 0);if (err) {libxdp_strerror(err, errmsg, sizeof(errmsg));fprintf(stderr, "Couldn't attach XDP program on iface '%s' : %s (%d)\n",cfg.ifname, errmsg, err);return err;}/* We also need to load the xsks_map */map = bpf_object__find_map_by_name(xdp_program__bpf_obj(prog), "xsks_map");xsk_map_fd = bpf_map__fd(map);if (xsk_map_fd < 0) {fprintf(stderr, "ERROR: no xsks map found: %s\n",strerror(xsk_map_fd));exit(EXIT_FAILURE);}}/* Allow unlimited locking of memory, so all memory needed for packet* buffers can be locked.** NOTE: since kernel v5.11, eBPF maps allocations are not tracked* through the process anymore. Now, eBPF maps are accounted to the* current cgroup of which the process that created the map is part of* (assuming the kernel was built with CONFIG_MEMCG).** Therefore, you should ensure an appropriate memory.max setting on* the cgroup (via sysfs, for example) instead of relying on rlimit.*/if (setrlimit(RLIMIT_MEMLOCK, &rlim)) {fprintf(stderr, "ERROR: setrlimit(RLIMIT_MEMLOCK) \"%s\"\n",strerror(errno));exit(EXIT_FAILURE);}/* Allocate memory for NUM_FRAMES of the default XDP frame size */packet_buffer_size = NUM_FRAMES * FRAME_SIZE;if (posix_memalign(&packet_buffer,getpagesize(), /* PAGE_SIZE aligned */packet_buffer_size)) {fprintf(stderr, "ERROR: Can't allocate buffer memory \"%s\"\n",strerror(errno));exit(EXIT_FAILURE);}/* Initialize shared packet_buffer for umem usage */umem = configure_xsk_umem(packet_buffer, packet_buffer_size);if (umem == NULL) {fprintf(stderr, "ERROR: Can't create umem \"%s\"\n",strerror(errno));exit(EXIT_FAILURE);}/* Open and configure the AF_XDP (xsk) socket */xsk_socket = xsk_configure_socket(&cfg, umem);if (xsk_socket == NULL) {fprintf(stderr, "ERROR: Can't setup AF_XDP socket \"%s\"\n",strerror(errno));exit(EXIT_FAILURE);}/* Start thread to do statistics display */if (verbose) {ret = pthread_create(&stats_poll_thread, NULL, stats_poll,xsk_socket);if (ret) {fprintf(stderr, "ERROR: Failed creating statistics thread ""\"%s\"\n", strerror(errno));exit(EXIT_FAILURE);}}/* Receive and count packets than drop them */rx_and_process(&cfg, xsk_socket);/* Cleanup */xsk_socket__delete(xsk_socket->xsk);xsk_umem__delete(umem->umem);return EXIT_OK;
}

Makefile (可能有一些别的依赖项)

如果想要通过make执行的话,可能还需要先去github里面下载一些必要的资源
把 makefile复制过来的时候突然发现到,缺少这些很有可能没法通过make编译
https://github.com/xdp-project/xdp-tutorial/blob/main/advanced03-AF_XDP/af_xdp_kern.c
可以先去上面把整个项目代码给下载下来先,然后把上面的用户态和内核态程序放到advanced03-AF_XDP文件夹下,代替底下的一些文件
因为我改过用户态和内核态的代码,将原来过滤icmp6改成了udp。具体你想是想什么效果,可以对比看看我改动了什么,然后参照我的写法把你的规则给添加进去。

# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)XDP_TARGETS  := af_xdp_kern
USER_TARGETS := af_xdp_user
LDLIBS += -lpthreadCOMMON_DIR := ../commoninclude $(COMMON_DIR)/common.mk
COMMON_OBJS := $(COMMON_DIR)/common_params.o
COMMON_OBJS += $(COMMON_DIR)/common_user_bpf_xdp.o

最后对端通过iperf指定端口udp类型以及流量进行打流,然后本端启用

./af_xdp_user -d enp3s0

具体用户态执行什么命令,可以看看用户态程序的入参处理函数,你就知道该添加什么参数,该怎么添加了
想要验证数据包会不会走linux内核协议栈,可以本端另开一个xshell窗口,tcpdump抓取指定网卡的数据包(执行tcpdump默认打开网口混杂模式),因为我想要验证udp,ipv6,所以tcpdump抓到一些邻居的数据,正常不用管,抓不到udp包说明数据包都给AF_socket的RX ringbuffer送到了用户态中

想要看看内核态程序有没有挂在xdp钩子上,或者是查看字节码信息等的,可以去问问deepseek,它都可以给出很好的答案
或者参考以下链接
https://thegraynode.io/posts/bpftool_introduction/

如果实在不了解xdp和ebpf的话,可以先去网上找找资料,或者去我上一篇文章找资料先看一下,对它先有个大致了解

http://www.dtcms.com/wzjs/167588.html

相关文章:

  • 阳江网络问政平台百度上做优化一年多少钱
  • 手机壁纸网站源码企业培训课程清单
  • 一流的高密做网站的百度竞价点击软件奔奔
  • 一个网站的建设方案北京网站维护公司
  • 专业网站建设价格企业网络营销策划案例
  • 免费网站建设平台手机优化是什么意思
  • 加盟网站模板常用的关键词挖掘工具有哪些
  • iis8.5 wordpress北京网站优化seo
  • 邯郸网站建设企业提高工作效率的方法
  • 黄冈网站排名最高国内手机搜索引擎十大排行
  • 外加工网优化法治化营商环境
  • 怎么查看网站是哪个公司做的国外免费域名
  • 中国开头的网站怎么做seo快速优化技术
  • 有没有可以做翻译的网站吗营销型网站seo
  • 台湾网站建设优化seo教程技术
  • 做面食视频网站网络营销五个主要手段
  • 线上运营公司seo中国
  • 电商型网站建设价格营业推广案例
  • 大连网站建设 领超最好互联网产品推广是做什么的
  • wordpress 安装 数据库重庆seo整站优化外包服务
  • 个人网站能干嘛爱网站关键词挖掘
  • 网站开发的母的目的和意义.网络营销课程培训机构
  • wordpress主题分享功能快速排序优化
  • 中文设计网站搜索引擎优化是什么意思啊
  • 上海到北京的机票武汉seo引擎优化
  • 利用花生壳做网站百度极速版客服人工在线咨询
  • 怎样自己做企业的网站制作自己的网站
  • 江油网站制作自己做的网站怎么推广
  • wordpress 标题换行沈阳seo整站优化
  • 专业的网站制作专业公司名站在线