cregit-Linux how code gets into the kernel

Release 4.10 samples/bpf/xdp_tx_iptunnel_user.c

Directory: samples/bpf
/* Copyright (c) 2016 Facebook
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 */
#include <linux/bpf.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <unistd.h>
#include <time.h>
#include "bpf_load.h"
#include "libbpf.h"
#include "bpf_util.h"
#include "xdp_tx_iptunnel_common.h"


#define STATS_INTERVAL_S 2U


static int ifindex = -1;


static void int_exit(int sig) { if (ifindex > -1) set_link_xdp_fd(ifindex, -1); exit(0); }

Contributors

PersonTokensPropCommitsCommitProp
martin kafai laumartin kafai lau29100.00%1100.00%
Total29100.00%1100.00%

/* simple per-protocol drop counter */
static void poll_stats(unsigned int kill_after_s) { const unsigned int nr_protos = 256; unsigned int nr_cpus = bpf_num_possible_cpus(); time_t started_at = time(NULL); __u64 values[nr_cpus], prev[nr_protos][nr_cpus]; __u32 proto; int i; memset(prev, 0, sizeof(prev)); while (!kill_after_s || time(NULL) - started_at <= kill_after_s) { sleep(STATS_INTERVAL_S); for (proto = 0; proto < nr_protos; proto++) { __u64 sum = 0; assert(bpf_map_lookup_elem(map_fd[0], &proto, values) == 0); for (i = 0; i < nr_cpus; i++) sum += (values[i] - prev[proto][i]); if (sum) printf("proto %u: sum:%10llu pkts, rate:%10llu pkts/s\n", proto, sum, sum / STATS_INTERVAL_S); memcpy(prev[proto], values, sizeof(values)); } } }

Contributors

PersonTokensPropCommitsCommitProp
martin kafai laumartin kafai lau18499.46%150.00%
joe stringerjoe stringer10.54%150.00%
Total185100.00%2100.00%


static void usage(const char *cmd) { printf("Start a XDP prog which encapsulates incoming packets\n" "in an IPv4/v6 header and XDP_TX it out. The dst <VIP:PORT>\n" "is used to select packets to encapsulate\n\n"); printf("Usage: %s [...]\n", cmd); printf(" -i <ifindex> Interface Index\n"); printf(" -a <vip-service-address> IPv4 or IPv6\n"); printf(" -p <vip-service-port> A port range (e.g. 433-444) is also allowed\n"); printf(" -s <source-ip> Used in the IPTunnel header\n"); printf(" -d <dest-ip> Used in the IPTunnel header\n"); printf(" -m <dest-MAC> Used in sending the IP Tunneled pkt\n"); printf(" -T <stop-after-X-seconds> Default: 0 (forever)\n"); printf(" -P <IP-Protocol> Default is TCP\n"); printf(" -h Display this help\n"); }

Contributors

PersonTokensPropCommitsCommitProp
martin kafai laumartin kafai lau70100.00%1100.00%
Total70100.00%1100.00%


static int parse_ipstr(const char *ipstr, unsigned int *addr) { if (inet_pton(AF_INET6, ipstr, addr) == 1) { return AF_INET6; } else if (inet_pton(AF_INET, ipstr, addr) == 1) { addr[1] = addr[2] = addr[3] = 0; return AF_INET; } fprintf(stderr, "%s is an invalid IP\n", ipstr); return AF_UNSPEC; }

Contributors

PersonTokensPropCommitsCommitProp
martin kafai laumartin kafai lau82100.00%1100.00%
Total82100.00%1100.00%


static int parse_ports(const char *port_str, int *min_port, int *max_port) { char *end; long tmp_min_port; long tmp_max_port; tmp_min_port = strtol(optarg, &end, 10); if (tmp_min_port < 1 || tmp_min_port > 65535) { fprintf(stderr, "Invalid port(s):%s\n", optarg); return 1; } if (*end == '-') { end++; tmp_max_port = strtol(end, NULL, 10); if (tmp_max_port < 1 || tmp_max_port > 65535) { fprintf(stderr, "Invalid port(s):%s\n", optarg); return 1; } } else { tmp_max_port = tmp_min_port; } if (tmp_min_port > tmp_max_port) { fprintf(stderr, "Invalid port(s):%s\n", optarg); return 1; } if (tmp_max_port - tmp_min_port + 1 > MAX_IPTNL_ENTRIES) { fprintf(stderr, "Port range (%s) is larger than %u\n", port_str, MAX_IPTNL_ENTRIES); return 1; } *min_port = tmp_min_port; *max_port = tmp_max_port; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
martin kafai laumartin kafai lau178100.00%1100.00%
Total178100.00%1100.00%


int main(int argc, char **argv) { unsigned char opt_flags[256] = {}; unsigned int kill_after_s = 0; const char *optstr = "i:a:p:s:d:m:T:P:h"; int min_port = 0, max_port = 0; struct iptnl_info tnl = {}; struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; struct vip vip = {}; char filename[256]; int opt; int i; tnl.family = AF_UNSPEC; vip.protocol = IPPROTO_TCP; for (i = 0; i < strlen(optstr); i++) if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z') opt_flags[(unsigned char)optstr[i]] = 1; while ((opt = getopt(argc, argv, optstr)) != -1) { unsigned short family; unsigned int *v6; switch (opt) { case 'i': ifindex = atoi(optarg); break; case 'a': vip.family = parse_ipstr(optarg, vip.daddr.v6); if (vip.family == AF_UNSPEC) return 1; break; case 'p': if (parse_ports(optarg, &min_port, &max_port)) return 1; break; case 'P': vip.protocol = atoi(optarg); break; case 's': case 'd': if (opt == 's') v6 = tnl.saddr.v6; else v6 = tnl.daddr.v6; family = parse_ipstr(optarg, v6); if (family == AF_UNSPEC) return 1; if (tnl.family == AF_UNSPEC) { tnl.family = family; } else if (tnl.family != family) { fprintf(stderr, "The IP version of the src and dst addresses used in the IP encapsulation does not match\n"); return 1; } break; case 'm': if (!ether_aton_r(optarg, (struct ether_addr *)tnl.dmac)) { fprintf(stderr, "Invalid mac address:%s\n", optarg); return 1; } break; case 'T': kill_after_s = atoi(optarg); break; default: usage(argv[0]); return 1; } opt_flags[opt] = 0; } for (i = 0; i < strlen(optstr); i++) { if (opt_flags[(unsigned int)optstr[i]]) { fprintf(stderr, "Missing argument -%c\n", optstr[i]); usage(argv[0]); return 1; } } if (setrlimit(RLIMIT_MEMLOCK, &r)) { perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)"); return 1; } snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); if (load_bpf_file(filename)) { printf("%s", bpf_log_buf); return 1; } if (!prog_fd[0]) { printf("load_bpf_file: %s\n", strerror(errno)); return 1; } signal(SIGINT, int_exit); while (min_port <= max_port) { vip.dport = htons(min_port++); if (bpf_map_update_elem(map_fd[1], &vip, &tnl, BPF_NOEXIST)) { perror("bpf_map_update_elem(&vip2tnl)"); return 1; } } if (set_link_xdp_fd(ifindex, prog_fd[0]) < 0) { printf("link set xdp fd failed\n"); return 1; } poll_stats(kill_after_s); set_link_xdp_fd(ifindex, -1); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
martin kafai laumartin kafai lau62999.68%150.00%
joe stringerjoe stringer20.32%150.00%
Total631100.00%2100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
martin kafai laumartin kafai lau123399.76%150.00%
joe stringerjoe stringer30.24%150.00%
Total1236100.00%2100.00%
Directory: samples/bpf
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.