Файловый менеджер - Редактировать - /var/www/xthruster/html/wp-content/uploads/flags/bpf.tar
Назад
test_cgrp2_sock.sh 0000755 00000005621 14722070530 0010202 0 ustar 00 #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # Test various socket options that can be set by attaching programs to cgroups. CGRP_MNT="/tmp/cgroupv2-test_cgrp2_sock" ################################################################################ # print_result() { local rc=$1 local status=" OK " [ $rc -ne 0 ] && status="FAIL" printf "%-50s [%4s]\n" "$2" "$status" } check_sock() { out=$(test_cgrp2_sock) echo $out | grep -q "$1" if [ $? -ne 0 ]; then print_result 1 "IPv4: $2" echo " expected: $1" echo " have: $out" rc=1 else print_result 0 "IPv4: $2" fi } check_sock6() { out=$(test_cgrp2_sock -6) echo $out | grep -q "$1" if [ $? -ne 0 ]; then print_result 1 "IPv6: $2" echo " expected: $1" echo " have: $out" rc=1 else print_result 0 "IPv6: $2" fi } ################################################################################ # cleanup() { echo $$ >> ${CGRP_MNT}/cgroup.procs rmdir ${CGRP_MNT}/sockopts } cleanup_and_exit() { local rc=$1 local msg="$2" [ -n "$msg" ] && echo "ERROR: $msg" test_cgrp2_sock -d ${CGRP_MNT}/sockopts ip li del cgrp2_sock umount ${CGRP_MNT} exit $rc } ################################################################################ # main rc=0 ip li add cgrp2_sock type dummy 2>/dev/null set -e mkdir -p ${CGRP_MNT} mount -t cgroup2 none ${CGRP_MNT} set +e # make sure we have a known start point cleanup 2>/dev/null mkdir -p ${CGRP_MNT}/sockopts [ $? -ne 0 ] && cleanup_and_exit 1 "Failed to create cgroup hierarchy" # set pid into cgroup echo $$ > ${CGRP_MNT}/sockopts/cgroup.procs # no bpf program attached, so socket should show no settings check_sock "dev , mark 0, priority 0" "No programs attached" check_sock6 "dev , mark 0, priority 0" "No programs attached" # verify device is set # test_cgrp2_sock -b cgrp2_sock ${CGRP_MNT}/sockopts if [ $? -ne 0 ]; then cleanup_and_exit 1 "Failed to install program to set device" fi check_sock "dev cgrp2_sock, mark 0, priority 0" "Device set" check_sock6 "dev cgrp2_sock, mark 0, priority 0" "Device set" # verify mark is set # test_cgrp2_sock -m 666 ${CGRP_MNT}/sockopts if [ $? -ne 0 ]; then cleanup_and_exit 1 "Failed to install program to set mark" fi check_sock "dev , mark 666, priority 0" "Mark set" check_sock6 "dev , mark 666, priority 0" "Mark set" # verify priority is set # test_cgrp2_sock -p 123 ${CGRP_MNT}/sockopts if [ $? -ne 0 ]; then cleanup_and_exit 1 "Failed to install program to set priority" fi check_sock "dev , mark 0, priority 123" "Priority set" check_sock6 "dev , mark 0, priority 123" "Priority set" # all 3 at once # test_cgrp2_sock -b cgrp2_sock -m 666 -p 123 ${CGRP_MNT}/sockopts if [ $? -ne 0 ]; then cleanup_and_exit 1 "Failed to install program to set device, mark and priority" fi check_sock "dev cgrp2_sock, mark 666, priority 123" "Priority set" check_sock6 "dev cgrp2_sock, mark 666, priority 123" "Priority set" cleanup_and_exit $rc run_cookie_uid_helper_example.sh 0000755 00000000525 14722070530 0013155 0 ustar 00 #!/bin/bash # SPDX-License-Identifier: GPL-2.0 local_dir="$(pwd)" root_dir=$local_dir/../.. mnt_dir=$(mktemp -d --tmp) on_exit() { iptables -D OUTPUT -m bpf --object-pinned ${mnt_dir}/bpf_prog -j ACCEPT umount ${mnt_dir} rm -r ${mnt_dir} } trap on_exit EXIT mount -t bpf bpf ${mnt_dir} ./per_socket_stats_example ${mnt_dir}/bpf_prog $1 tc_l2_redirect.sh 0000755 00000011640 14722070530 0007771 0 ustar 00 #!/bin/bash # SPDX-License-Identifier: GPL-2.0 [[ -z $TC ]] && TC='tc' [[ -z $IP ]] && IP='ip' REDIRECT_USER='./tc_l2_redirect' REDIRECT_BPF='./tc_l2_redirect_kern.o' RP_FILTER=$(< /proc/sys/net/ipv4/conf/all/rp_filter) IPV6_FORWARDING=$(< /proc/sys/net/ipv6/conf/all/forwarding) function config_common { local tun_type=$1 $IP netns add ns1 $IP netns add ns2 $IP link add ve1 type veth peer name vens1 $IP link add ve2 type veth peer name vens2 $IP link set dev ve1 up $IP link set dev ve2 up $IP link set dev ve1 mtu 1500 $IP link set dev ve2 mtu 1500 $IP link set dev vens1 netns ns1 $IP link set dev vens2 netns ns2 $IP -n ns1 link set dev lo up $IP -n ns1 link set dev vens1 up $IP -n ns1 addr add 10.1.1.101/24 dev vens1 $IP -n ns1 addr add 2401:db01::65/64 dev vens1 nodad $IP -n ns1 route add default via 10.1.1.1 dev vens1 $IP -n ns1 route add default via 2401:db01::1 dev vens1 $IP -n ns2 link set dev lo up $IP -n ns2 link set dev vens2 up $IP -n ns2 addr add 10.2.1.102/24 dev vens2 $IP -n ns2 addr add 2401:db02::66/64 dev vens2 nodad $IP -n ns2 addr add 10.10.1.102 dev lo $IP -n ns2 addr add 2401:face::66/64 dev lo nodad $IP -n ns2 link add ipt2 type ipip local 10.2.1.102 remote 10.2.1.1 $IP -n ns2 link add ip6t2 type ip6tnl mode any local 2401:db02::66 remote 2401:db02::1 $IP -n ns2 link set dev ipt2 up $IP -n ns2 link set dev ip6t2 up $IP netns exec ns2 $TC qdisc add dev vens2 clsact $IP netns exec ns2 $TC filter add dev vens2 ingress bpf da obj $REDIRECT_BPF sec drop_non_tun_vip if [[ $tun_type == "ipip" ]]; then $IP -n ns2 route add 10.1.1.0/24 dev ipt2 $IP netns exec ns2 sysctl -q -w net.ipv4.conf.all.rp_filter=0 $IP netns exec ns2 sysctl -q -w net.ipv4.conf.ipt2.rp_filter=0 else $IP -n ns2 route add 10.1.1.0/24 dev ip6t2 $IP -n ns2 route add 2401:db01::/64 dev ip6t2 $IP netns exec ns2 sysctl -q -w net.ipv4.conf.all.rp_filter=0 $IP netns exec ns2 sysctl -q -w net.ipv4.conf.ip6t2.rp_filter=0 fi $IP addr add 10.1.1.1/24 dev ve1 $IP addr add 2401:db01::1/64 dev ve1 nodad $IP addr add 10.2.1.1/24 dev ve2 $IP addr add 2401:db02::1/64 dev ve2 nodad $TC qdisc add dev ve2 clsact $TC filter add dev ve2 ingress bpf da obj $REDIRECT_BPF sec l2_to_iptun_ingress_forward sysctl -q -w net.ipv4.conf.all.rp_filter=0 sysctl -q -w net.ipv6.conf.all.forwarding=1 } function cleanup { set +e [[ -z $DEBUG ]] || set +x $IP netns delete ns1 >& /dev/null $IP netns delete ns2 >& /dev/null $IP link del ve1 >& /dev/null $IP link del ve2 >& /dev/null $IP link del ipt >& /dev/null $IP link del ip6t >& /dev/null sysctl -q -w net.ipv4.conf.all.rp_filter=$RP_FILTER sysctl -q -w net.ipv6.conf.all.forwarding=$IPV6_FORWARDING rm -f /sys/fs/bpf/tc/globals/tun_iface [[ -z $DEBUG ]] || set -x set -e } function l2_to_ipip { echo -n "l2_to_ipip $1: " local dir=$1 config_common ipip $IP link add ipt type ipip external $IP link set dev ipt up sysctl -q -w net.ipv4.conf.ipt.rp_filter=0 sysctl -q -w net.ipv4.conf.ipt.forwarding=1 if [[ $dir == "egress" ]]; then $IP route add 10.10.1.0/24 via 10.2.1.102 dev ve2 $TC filter add dev ve2 egress bpf da obj $REDIRECT_BPF sec l2_to_iptun_ingress_redirect sysctl -q -w net.ipv4.conf.ve1.forwarding=1 else $TC qdisc add dev ve1 clsact $TC filter add dev ve1 ingress bpf da obj $REDIRECT_BPF sec l2_to_iptun_ingress_redirect fi $REDIRECT_USER -U /sys/fs/bpf/tc/globals/tun_iface -i $(< /sys/class/net/ipt/ifindex) $IP netns exec ns1 ping -c1 10.10.1.102 >& /dev/null if [[ $dir == "egress" ]]; then # test direct egress to ve2 (i.e. not forwarding from # ve1 to ve2). ping -c1 10.10.1.102 >& /dev/null fi cleanup echo "OK" } function l2_to_ip6tnl { echo -n "l2_to_ip6tnl $1: " local dir=$1 config_common ip6tnl $IP link add ip6t type ip6tnl mode any external $IP link set dev ip6t up sysctl -q -w net.ipv4.conf.ip6t.rp_filter=0 sysctl -q -w net.ipv4.conf.ip6t.forwarding=1 if [[ $dir == "egress" ]]; then $IP route add 10.10.1.0/24 via 10.2.1.102 dev ve2 $IP route add 2401:face::/64 via 2401:db02::66 dev ve2 $TC filter add dev ve2 egress bpf da obj $REDIRECT_BPF sec l2_to_ip6tun_ingress_redirect sysctl -q -w net.ipv4.conf.ve1.forwarding=1 else $TC qdisc add dev ve1 clsact $TC filter add dev ve1 ingress bpf da obj $REDIRECT_BPF sec l2_to_ip6tun_ingress_redirect fi $REDIRECT_USER -U /sys/fs/bpf/tc/globals/tun_iface -i $(< /sys/class/net/ip6t/ifindex) $IP netns exec ns1 ping -c1 10.10.1.102 >& /dev/null $IP netns exec ns1 ping -6 -c1 2401:face::66 >& /dev/null if [[ $dir == "egress" ]]; then # test direct egress to ve2 (i.e. not forwarding from # ve1 to ve2). ping -c1 10.10.1.102 >& /dev/null ping -6 -c1 2401:face::66 >& /dev/null fi cleanup echo "OK" } cleanup test_names="l2_to_ipip l2_to_ip6tnl" test_dirs="ingress egress" if [[ $# -ge 2 ]]; then test_names=$1 test_dirs=$2 elif [[ $# -ge 1 ]]; then test_names=$1 fi for t in $test_names; do for d in $test_dirs; do $t $d done done test_override_return.sh 0000755 00000000424 14722070530 0011360 0 ustar 00 #!/bin/bash rm -r tmpmnt rm -f testfile.img dd if=/dev/zero of=testfile.img bs=1M seek=1000 count=1 DEVICE=$(losetup --show -f testfile.img) mkfs.btrfs -f $DEVICE mkdir tmpmnt ./tracex7 $DEVICE if [ $? -eq 0 ] then echo "SUCCESS!" else echo "FAILED!" fi losetup -d $DEVICE test_ipip.sh 0000755 00000013130 14722070530 0007101 0 ustar 00 #!/bin/bash # SPDX-License-Identifier: GPL-2.0 function config_device { ip netns add at_ns0 ip netns add at_ns1 ip netns add at_ns2 ip link add veth0 type veth peer name veth0b ip link add veth1 type veth peer name veth1b ip link add veth2 type veth peer name veth2b ip link set veth0b up ip link set veth1b up ip link set veth2b up ip link set dev veth0b mtu 1500 ip link set dev veth1b mtu 1500 ip link set dev veth2b mtu 1500 ip link set veth0 netns at_ns0 ip link set veth1 netns at_ns1 ip link set veth2 netns at_ns2 ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth0 ip netns exec at_ns0 ip addr add 2401:db00::1/64 dev veth0 nodad ip netns exec at_ns0 ip link set dev veth0 up ip netns exec at_ns1 ip addr add 172.16.1.101/24 dev veth1 ip netns exec at_ns1 ip addr add 2401:db00::2/64 dev veth1 nodad ip netns exec at_ns1 ip link set dev veth1 up ip netns exec at_ns2 ip addr add 172.16.1.200/24 dev veth2 ip netns exec at_ns2 ip addr add 2401:db00::3/64 dev veth2 nodad ip netns exec at_ns2 ip link set dev veth2 up ip link add br0 type bridge ip link set br0 up ip link set dev br0 mtu 1500 ip link set veth0b master br0 ip link set veth1b master br0 ip link set veth2b master br0 } function add_ipip_tunnel { ip netns exec at_ns0 \ ip link add dev $DEV_NS type ipip local 172.16.1.100 remote 172.16.1.200 ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns1 \ ip link add dev $DEV_NS type ipip local 172.16.1.101 remote 172.16.1.200 ip netns exec at_ns1 ip link set dev $DEV_NS up # same inner IP address in at_ns0 and at_ns1 ip netns exec at_ns1 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns2 ip link add dev $DEV type ipip external ip netns exec at_ns2 ip link set dev $DEV up ip netns exec at_ns2 ip addr add dev $DEV 10.1.1.200/24 } function add_ipip6_tunnel { ip netns exec at_ns0 \ ip link add dev $DEV_NS type ip6tnl mode ipip6 local 2401:db00::1/64 remote 2401:db00::3/64 ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns1 \ ip link add dev $DEV_NS type ip6tnl mode ipip6 local 2401:db00::2/64 remote 2401:db00::3/64 ip netns exec at_ns1 ip link set dev $DEV_NS up # same inner IP address in at_ns0 and at_ns1 ip netns exec at_ns1 ip addr add dev $DEV_NS 10.1.1.100/24 ip netns exec at_ns2 ip link add dev $DEV type ip6tnl mode ipip6 external ip netns exec at_ns2 ip link set dev $DEV up ip netns exec at_ns2 ip addr add dev $DEV 10.1.1.200/24 } function add_ip6ip6_tunnel { ip netns exec at_ns0 \ ip link add dev $DEV_NS type ip6tnl mode ip6ip6 local 2401:db00::1/64 remote 2401:db00::3/64 ip netns exec at_ns0 ip link set dev $DEV_NS up ip netns exec at_ns0 ip addr add dev $DEV_NS 2601:646::1/64 ip netns exec at_ns1 \ ip link add dev $DEV_NS type ip6tnl mode ip6ip6 local 2401:db00::2/64 remote 2401:db00::3/64 ip netns exec at_ns1 ip link set dev $DEV_NS up # same inner IP address in at_ns0 and at_ns1 ip netns exec at_ns1 ip addr add dev $DEV_NS 2601:646::1/64 ip netns exec at_ns2 ip link add dev $DEV type ip6tnl mode ip6ip6 external ip netns exec at_ns2 ip link set dev $DEV up ip netns exec at_ns2 ip addr add dev $DEV 2601:646::2/64 } function attach_bpf { DEV=$1 SET_TUNNEL=$2 GET_TUNNEL=$3 ip netns exec at_ns2 tc qdisc add dev $DEV clsact ip netns exec at_ns2 tc filter add dev $DEV egress bpf da obj tcbpf2_kern.o sec $SET_TUNNEL ip netns exec at_ns2 tc filter add dev $DEV ingress bpf da obj tcbpf2_kern.o sec $GET_TUNNEL } function test_ipip { DEV_NS=ipip_std DEV=ipip_bpf config_device # tcpdump -nei br0 & cat /sys/kernel/debug/tracing/trace_pipe & add_ipip_tunnel attach_bpf $DEV ipip_set_tunnel ipip_get_tunnel ip netns exec at_ns0 ping -c 1 10.1.1.200 ip netns exec at_ns2 ping -c 1 10.1.1.100 ip netns exec at_ns0 iperf -sD -p 5200 > /dev/null ip netns exec at_ns1 iperf -sD -p 5201 > /dev/null sleep 0.2 # tcp check _same_ IP over different tunnels ip netns exec at_ns2 iperf -c 10.1.1.100 -n 5k -p 5200 ip netns exec at_ns2 iperf -c 10.1.1.100 -n 5k -p 5201 cleanup } # IPv4 over IPv6 tunnel function test_ipip6 { DEV_NS=ipip_std DEV=ipip_bpf config_device # tcpdump -nei br0 & cat /sys/kernel/debug/tracing/trace_pipe & add_ipip6_tunnel attach_bpf $DEV ipip6_set_tunnel ipip6_get_tunnel ip netns exec at_ns0 ping -c 1 10.1.1.200 ip netns exec at_ns2 ping -c 1 10.1.1.100 ip netns exec at_ns0 iperf -sD -p 5200 > /dev/null ip netns exec at_ns1 iperf -sD -p 5201 > /dev/null sleep 0.2 # tcp check _same_ IP over different tunnels ip netns exec at_ns2 iperf -c 10.1.1.100 -n 5k -p 5200 ip netns exec at_ns2 iperf -c 10.1.1.100 -n 5k -p 5201 cleanup } # IPv6 over IPv6 tunnel function test_ip6ip6 { DEV_NS=ipip_std DEV=ipip_bpf config_device # tcpdump -nei br0 & cat /sys/kernel/debug/tracing/trace_pipe & add_ip6ip6_tunnel attach_bpf $DEV ip6ip6_set_tunnel ip6ip6_get_tunnel ip netns exec at_ns0 ping -6 -c 1 2601:646::2 ip netns exec at_ns2 ping -6 -c 1 2601:646::1 ip netns exec at_ns0 iperf -6sD -p 5200 > /dev/null ip netns exec at_ns1 iperf -6sD -p 5201 > /dev/null sleep 0.2 # tcp check _same_ IP over different tunnels ip netns exec at_ns2 iperf -6c 2601:646::1 -n 5k -p 5200 ip netns exec at_ns2 iperf -6c 2601:646::1 -n 5k -p 5201 cleanup } function cleanup { set +ex pkill iperf ip netns delete at_ns0 ip netns delete at_ns1 ip netns delete at_ns2 ip link del veth0 ip link del veth1 ip link del veth2 ip link del br0 pkill tcpdump pkill cat set -ex } cleanup echo "Testing IP tunnels..." test_ipip test_ipip6 test_ip6ip6 echo "*** PASS ***" xdp2skb_meta.sh 0000755 00000011002 14722070530 0007460 0 ustar 00 #!/bin/bash # # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2018 Jesper Dangaard Brouer, Red Hat Inc. # # Bash-shell example on using iproute2 tools 'tc' and 'ip' to load # eBPF programs, both for XDP and clsbpf. Shell script function # wrappers and even long options parsing is illustrated, for ease of # use. # # Related to sample/bpf/xdp2skb_meta_kern.c, which contains BPF-progs # that need to collaborate between XDP and TC hooks. Thus, it is # convenient that the same tool load both programs that need to work # together. # BPF_FILE=xdp2skb_meta_kern.o DIR=$(dirname $0) [ -z "$TC" ] && TC=tc [ -z "$IP" ] && IP=ip function usage() { echo "" echo "Usage: $0 [-vfh] --dev ethX" echo " -d | --dev : Network device (required)" echo " --flush : Cleanup flush TC and XDP progs" echo " --list : (\$LIST) List TC and XDP progs" echo " -v | --verbose : (\$VERBOSE) Verbose" echo " --dry-run : (\$DRYRUN) Dry-run only (echo commands)" echo "" } ## -- General shell logging cmds -- function err() { local exitcode=$1 shift echo "ERROR: $@" >&2 exit $exitcode } function info() { if [[ -n "$VERBOSE" ]]; then echo "# $@" fi } ## -- Helper function calls -- # Wrapper call for TC and IP # - Will display the offending command on failure function _call_cmd() { local cmd="$1" local allow_fail="$2" shift 2 if [[ -n "$VERBOSE" ]]; then echo "$cmd $@" fi if [[ -n "$DRYRUN" ]]; then return fi $cmd "$@" local status=$? if (( $status != 0 )); then if [[ "$allow_fail" == "" ]]; then err 2 "Exec error($status) occurred cmd: \"$cmd $@\"" fi fi } function call_tc() { _call_cmd "$TC" "" "$@" } function call_tc_allow_fail() { _call_cmd "$TC" "allow_fail" "$@" } function call_ip() { _call_cmd "$IP" "" "$@" } ## --- Parse command line arguments / parameters --- # Using external program "getopt" to get --long-options OPTIONS=$(getopt -o vfhd: \ --long verbose,flush,help,list,dev:,dry-run -- "$@") if (( $? != 0 )); then err 4 "Error calling getopt" fi eval set -- "$OPTIONS" unset DEV unset FLUSH while true; do case "$1" in -d | --dev ) # device DEV=$2 info "Device set to: DEV=$DEV" >&2 shift 2 ;; -v | --verbose) VERBOSE=yes # info "Verbose mode: VERBOSE=$VERBOSE" >&2 shift ;; --dry-run ) DRYRUN=yes VERBOSE=yes info "Dry-run mode: enable VERBOSE and don't call TC+IP" >&2 shift ;; -f | --flush ) FLUSH=yes shift ;; --list ) LIST=yes shift ;; -- ) shift break ;; -h | --help ) usage; exit 0 ;; * ) shift break ;; esac done FILE="$DIR/$BPF_FILE" if [[ ! -e $FILE ]]; then err 3 "Missing BPF object file ($FILE)" fi if [[ -z $DEV ]]; then usage err 2 "Please specify network device -- required option --dev" fi ## -- Function calls -- function list_tc() { local device="$1" shift info "Listing current TC ingress rules" call_tc filter show dev $device ingress } function list_xdp() { local device="$1" shift info "Listing current XDP device($device) setting" call_ip link show dev $device | grep --color=auto xdp } function flush_tc() { local device="$1" shift info "Flush TC on device: $device" call_tc_allow_fail filter del dev $device ingress call_tc_allow_fail qdisc del dev $device clsact } function flush_xdp() { local device="$1" shift info "Flush XDP on device: $device" call_ip link set dev $device xdp off } function attach_tc_mark() { local device="$1" local file="$2" local prog="tc_mark" shift 2 # Re-attach clsact to clear/flush existing role call_tc_allow_fail qdisc del dev $device clsact 2> /dev/null call_tc qdisc add dev $device clsact # Attach BPF prog call_tc filter add dev $device ingress \ prio 1 handle 1 bpf da obj $file sec $prog } function attach_xdp_mark() { local device="$1" local file="$2" local prog="xdp_mark" shift 2 # Remove XDP prog in-case it's already loaded # TODO: Need ip-link option to override/replace existing XDP prog flush_xdp $device # Attach XDP/BPF prog call_ip link set dev $device xdp obj $file sec $prog } if [[ -n $FLUSH ]]; then flush_tc $DEV flush_xdp $DEV exit 0 fi if [[ -n $LIST ]]; then list_tc $DEV list_xdp $DEV exit 0 fi attach_tc_mark $DEV $FILE attach_xdp_mark $DEV $FILE lwt_len_hist.sh 0000755 00000002027 14722070530 0007577 0 ustar 00 #!/bin/bash # SPDX-License-Identifier: GPL-2.0 NS1=lwt_ns1 VETH0=tst_lwt1a VETH1=tst_lwt1b TRACE_ROOT=/sys/kernel/debug/tracing function cleanup { # To reset saved histogram, remove pinned map rm /sys/fs/bpf/tc/globals/lwt_len_hist_map ip route del 192.168.253.2/32 dev $VETH0 2> /dev/null ip link del $VETH0 2> /dev/null ip link del $VETH1 2> /dev/null ip netns exec $NS1 killall netserver ip netns delete $NS1 2> /dev/null } cleanup ip netns add $NS1 ip link add $VETH0 type veth peer name $VETH1 ip link set dev $VETH0 up ip addr add 192.168.253.1/24 dev $VETH0 ip link set $VETH1 netns $NS1 ip netns exec $NS1 ip link set dev $VETH1 up ip netns exec $NS1 ip addr add 192.168.253.2/24 dev $VETH1 ip netns exec $NS1 netserver echo 1 > ${TRACE_ROOT}/tracing_on cp /dev/null ${TRACE_ROOT}/trace ip route add 192.168.253.2/32 encap bpf out obj lwt_len_hist_kern.o section len_hist dev $VETH0 netperf -H 192.168.253.2 -t TCP_STREAM cat ${TRACE_ROOT}/trace | grep -v '^#' ./lwt_len_hist cleanup echo 0 > ${TRACE_ROOT}/tracing_on exit 0 test_lwt_bpf.sh 0000755 00000021722 14722070530 0007603 0 ustar 00 #!/bin/bash # SPDX-License-Identifier: GPL-2.0 # Uncomment to see generated bytecode #VERBOSE=verbose NS1=lwt_ns1 NS2=lwt_ns2 VETH0=tst_lwt1a VETH1=tst_lwt1b VETH2=tst_lwt2a VETH3=tst_lwt2b IPVETH0="192.168.254.1" IPVETH1="192.168.254.2" IPVETH1b="192.168.254.3" IPVETH2="192.168.111.1" IPVETH3="192.168.111.2" IP_LOCAL="192.168.99.1" TRACE_ROOT=/sys/kernel/debug/tracing function lookup_mac() { set +x if [ ! -z "$2" ]; then MAC=$(ip netns exec $2 ip link show $1 | grep ether | awk '{print $2}') else MAC=$(ip link show $1 | grep ether | awk '{print $2}') fi MAC="${MAC//:/}" echo "0x${MAC:10:2}${MAC:8:2}${MAC:6:2}${MAC:4:2}${MAC:2:2}${MAC:0:2}" set -x } function cleanup { set +ex rm test_lwt_bpf.o 2> /dev/null ip link del $VETH0 2> /dev/null ip link del $VETH1 2> /dev/null ip link del $VETH2 2> /dev/null ip link del $VETH3 2> /dev/null ip netns exec $NS1 killall netserver ip netns delete $NS1 2> /dev/null ip netns delete $NS2 2> /dev/null set -ex } function setup_one_veth { ip netns add $1 ip link add $2 type veth peer name $3 ip link set dev $2 up ip addr add $4/24 dev $2 ip link set $3 netns $1 ip netns exec $1 ip link set dev $3 up ip netns exec $1 ip addr add $5/24 dev $3 if [ "$6" ]; then ip netns exec $1 ip addr add $6/32 dev $3 fi } function get_trace { set +x cat ${TRACE_ROOT}/trace | grep -v '^#' set -x } function cleanup_routes { ip route del ${IPVETH1}/32 dev $VETH0 2> /dev/null || true ip route del table local local ${IP_LOCAL}/32 dev lo 2> /dev/null || true } function install_test { cleanup_routes cp /dev/null ${TRACE_ROOT}/trace OPTS="encap bpf headroom 14 $1 obj test_lwt_bpf.o section $2 $VERBOSE" if [ "$1" == "in" ]; then ip route add table local local ${IP_LOCAL}/32 $OPTS dev lo else ip route add ${IPVETH1}/32 $OPTS dev $VETH0 fi } function remove_prog { if [ "$1" == "in" ]; then ip route del table local local ${IP_LOCAL}/32 dev lo else ip route del ${IPVETH1}/32 dev $VETH0 fi } function filter_trace { # Add newline to allow starting EXPECT= variables on newline NL=$'\n' echo "${NL}$*" | sed -e 's/^.*: : //g' } function expect_fail { set +x echo "FAIL:" echo "Expected: $1" echo "Got: $2" set -x exit 1 } function match_trace { set +x RET=0 TRACE=$1 EXPECT=$2 GOT="$(filter_trace "$TRACE")" [ "$GOT" != "$EXPECT" ] && { expect_fail "$EXPECT" "$GOT" RET=1 } set -x return $RET } function test_start { set +x echo "----------------------------------------------------------------" echo "Starting test: $*" echo "----------------------------------------------------------------" set -x } function failure { get_trace echo "FAIL: $*" exit 1 } function test_ctx_xmit { test_start "test_ctx on lwt xmit" install_test xmit test_ctx ping -c 3 $IPVETH1 || { failure "test_ctx xmit: packets are dropped" } match_trace "$(get_trace)" " len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX" || exit 1 remove_prog xmit } function test_ctx_out { test_start "test_ctx on lwt out" install_test out test_ctx ping -c 3 $IPVETH1 || { failure "test_ctx out: packets are dropped" } match_trace "$(get_trace)" " len 84 hash 0 protocol 0 cb 1234 ingress_ifindex 0 ifindex 0 len 84 hash 0 protocol 0 cb 1234 ingress_ifindex 0 ifindex 0 len 84 hash 0 protocol 0 cb 1234 ingress_ifindex 0 ifindex 0" || exit 1 remove_prog out } function test_ctx_in { test_start "test_ctx on lwt in" install_test in test_ctx ping -c 3 $IP_LOCAL || { failure "test_ctx out: packets are dropped" } # We will both request & reply packets as the packets will # be from $IP_LOCAL => $IP_LOCAL match_trace "$(get_trace)" " len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 1 ifindex 1 len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 1 ifindex 1 len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 1 ifindex 1 len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 1 ifindex 1 len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 1 ifindex 1 len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 1 ifindex 1" || exit 1 remove_prog in } function test_data { test_start "test_data on lwt $1" install_test $1 test_data ping -c 3 $IPVETH1 || { failure "test_data ${1}: packets are dropped" } match_trace "$(get_trace)" " src: 1fea8c0 dst: 2fea8c0 src: 1fea8c0 dst: 2fea8c0 src: 1fea8c0 dst: 2fea8c0" || exit 1 remove_prog $1 } function test_data_in { test_start "test_data on lwt in" install_test in test_data ping -c 3 $IP_LOCAL || { failure "test_data in: packets are dropped" } # We will both request & reply packets as the packets will # be from $IP_LOCAL => $IP_LOCAL match_trace "$(get_trace)" " src: 163a8c0 dst: 163a8c0 src: 163a8c0 dst: 163a8c0 src: 163a8c0 dst: 163a8c0 src: 163a8c0 dst: 163a8c0 src: 163a8c0 dst: 163a8c0 src: 163a8c0 dst: 163a8c0" || exit 1 remove_prog in } function test_cb { test_start "test_cb on lwt $1" install_test $1 test_cb ping -c 3 $IPVETH1 || { failure "test_cb ${1}: packets are dropped" } match_trace "$(get_trace)" " cb0: 0 cb1: 0 cb2: 0 cb3: 0 cb4: 0 cb0: 0 cb1: 0 cb2: 0 cb3: 0 cb4: 0 cb0: 0 cb1: 0 cb2: 0 cb3: 0 cb4: 0" || exit 1 remove_prog $1 } function test_cb_in { test_start "test_cb on lwt in" install_test in test_cb ping -c 3 $IP_LOCAL || { failure "test_cb in: packets are dropped" } # We will both request & reply packets as the packets will # be from $IP_LOCAL => $IP_LOCAL match_trace "$(get_trace)" " cb0: 0 cb1: 0 cb2: 0 cb3: 0 cb4: 0 cb0: 0 cb1: 0 cb2: 0 cb3: 0 cb4: 0 cb0: 0 cb1: 0 cb2: 0 cb3: 0 cb4: 0 cb0: 0 cb1: 0 cb2: 0 cb3: 0 cb4: 0 cb0: 0 cb1: 0 cb2: 0 cb3: 0 cb4: 0 cb0: 0 cb1: 0 cb2: 0 cb3: 0 cb4: 0" || exit 1 remove_prog in } function test_drop_all { test_start "test_drop_all on lwt $1" install_test $1 drop_all ping -c 3 $IPVETH1 && { failure "test_drop_all ${1}: Unexpected success of ping" } match_trace "$(get_trace)" " dropping with: 2 dropping with: 2 dropping with: 2" || exit 1 remove_prog $1 } function test_drop_all_in { test_start "test_drop_all on lwt in" install_test in drop_all ping -c 3 $IP_LOCAL && { failure "test_drop_all in: Unexpected success of ping" } match_trace "$(get_trace)" " dropping with: 2 dropping with: 2 dropping with: 2" || exit 1 remove_prog in } function test_push_ll_and_redirect { test_start "test_push_ll_and_redirect on lwt xmit" install_test xmit push_ll_and_redirect ping -c 3 $IPVETH1 || { failure "Redirected packets appear to be dropped" } match_trace "$(get_trace)" " redirected to $DST_IFINDEX redirected to $DST_IFINDEX redirected to $DST_IFINDEX" || exit 1 remove_prog xmit } function test_no_l2_and_redirect { test_start "test_no_l2_and_redirect on lwt xmit" install_test xmit fill_garbage_and_redirect ping -c 3 $IPVETH1 && { failure "Unexpected success despite lack of L2 header" } match_trace "$(get_trace)" " redirected to $DST_IFINDEX redirected to $DST_IFINDEX redirected to $DST_IFINDEX" || exit 1 remove_prog xmit } function test_rewrite { test_start "test_rewrite on lwt xmit" install_test xmit test_rewrite ping -c 3 $IPVETH1 || { failure "Rewritten packets appear to be dropped" } match_trace "$(get_trace)" " out: rewriting from 2fea8c0 to 3fea8c0 out: rewriting from 2fea8c0 to 3fea8c0 out: rewriting from 2fea8c0 to 3fea8c0" || exit 1 remove_prog out } function test_fill_garbage { test_start "test_fill_garbage on lwt xmit" install_test xmit fill_garbage ping -c 3 $IPVETH1 && { failure "test_drop_all ${1}: Unexpected success of ping" } match_trace "$(get_trace)" " Set initial 96 bytes of header to FF Set initial 96 bytes of header to FF Set initial 96 bytes of header to FF" || exit 1 remove_prog xmit } function test_netperf_nop { test_start "test_netperf_nop on lwt xmit" install_test xmit nop netperf -H $IPVETH1 -t TCP_STREAM || { failure "packets appear to be dropped" } match_trace "$(get_trace)" ""|| exit 1 remove_prog xmit } function test_netperf_redirect { test_start "test_netperf_redirect on lwt xmit" install_test xmit push_ll_and_redirect_silent netperf -H $IPVETH1 -t TCP_STREAM || { failure "Rewritten packets appear to be dropped" } match_trace "$(get_trace)" ""|| exit 1 remove_prog xmit } cleanup setup_one_veth $NS1 $VETH0 $VETH1 $IPVETH0 $IPVETH1 $IPVETH1b setup_one_veth $NS2 $VETH2 $VETH3 $IPVETH2 $IPVETH3 ip netns exec $NS1 netserver echo 1 > ${TRACE_ROOT}/tracing_on DST_MAC=$(lookup_mac $VETH1 $NS1) SRC_MAC=$(lookup_mac $VETH0) DST_IFINDEX=$(cat /sys/class/net/$VETH0/ifindex) CLANG_OPTS="-O2 -target bpf -I ../include/" CLANG_OPTS+=" -DSRC_MAC=$SRC_MAC -DDST_MAC=$DST_MAC -DDST_IFINDEX=$DST_IFINDEX" clang $CLANG_OPTS -c test_lwt_bpf.c -o test_lwt_bpf.o test_ctx_xmit test_ctx_out test_ctx_in test_data "xmit" test_data "out" test_data_in test_cb "xmit" test_cb "out" test_cb_in test_drop_all "xmit" test_drop_all "out" test_drop_all_in test_rewrite test_push_ll_and_redirect test_no_l2_and_redirect test_fill_garbage test_netperf_nop test_netperf_redirect cleanup echo 0 > ${TRACE_ROOT}/tracing_on exit 0 test_cls_bpf.sh 0000755 00000001623 14722070530 0007554 0 ustar 00 #!/bin/bash # SPDX-License-Identifier: GPL-2.0 function pktgen { ../pktgen/pktgen_bench_xmit_mode_netif_receive.sh -i $IFC -s 64 \ -m 90:e2:ba:ff:ff:ff -d 192.168.0.1 -t 4 local dropped=`tc -s qdisc show dev $IFC | tail -3 | awk '/drop/{print $7}'` if [ "$dropped" == "0," ]; then echo "FAIL" else echo "Successfully filtered " $dropped " packets" fi } function test { echo -n "Loading bpf program '$2'... " tc qdisc add dev $IFC clsact tc filter add dev $IFC ingress bpf da obj $1 sec $2 local status=$? if [ $status -ne 0 ]; then echo "FAIL" else echo "ok" pktgen fi tc qdisc del dev $IFC clsact } IFC=test_veth ip link add name $IFC type veth peer name pair_$IFC ip link set $IFC up ip link set pair_$IFC up test ./parse_simple.o simple test ./parse_varlen.o varlen test ./parse_ldabs.o ldabs ip link del dev $IFC Makefile 0000644 00000006106 14722070530 0006207 0 ustar 00 # SPDX-License-Identifier: GPL-2.0 include ../scripts/Makefile.include prefix ?= /usr/local CC = gcc LEX = flex YACC = bison MAKE = make INSTALL ?= install CFLAGS += -Wall -O2 CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/include/uapi -I$(srctree)/include # This will work when bpf is built in tools env. where srctree # isn't set and when invoked from selftests build, where srctree # is set to ".". building_out_of_srctree is undefined for in srctree # builds ifeq ($(srctree),) update_srctree := 1 endif ifndef building_out_of_srctree update_srctree := 1 endif ifeq ($(update_srctree),1) srctree := $(patsubst %/,%,$(dir $(CURDIR))) srctree := $(patsubst %/,%,$(dir $(srctree))) endif ifeq ($(V),1) Q = else Q = @ endif FEATURE_USER = .bpf FEATURE_TESTS = libbfd disassembler-four-args FEATURE_DISPLAY = libbfd disassembler-four-args check_feat := 1 NON_CHECK_FEAT_TARGETS := clean bpftool_clean ifdef MAKECMDGOALS ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),) check_feat := 0 endif endif ifeq ($(check_feat),1) ifeq ($(FEATURES_DUMP),) include $(srctree)/tools/build/Makefile.feature else include $(FEATURES_DUMP) endif endif ifeq ($(feature-disassembler-four-args), 1) CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE endif $(OUTPUT)%.yacc.c: $(srctree)/tools/bpf/%.y $(QUIET_BISON)$(YACC) -o $@ -d $< $(OUTPUT)%.lex.c: $(srctree)/tools/bpf/%.l $(QUIET_FLEX)$(LEX) -o $@ $< $(OUTPUT)%.o: $(srctree)/tools/bpf/%.c $(QUIET_CC)$(COMPILE.c) -o $@ $< $(OUTPUT)%.yacc.o: $(OUTPUT)%.yacc.c $(QUIET_CC)$(COMPILE.c) -o $@ $< $(OUTPUT)%.lex.o: $(OUTPUT)%.lex.c $(QUIET_CC)$(COMPILE.c) -o $@ $< PROGS = $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg $(OUTPUT)bpf_asm all: $(PROGS) bpftool $(OUTPUT)bpf_jit_disasm: CFLAGS += -DPACKAGE='bpf_jit_disasm' $(OUTPUT)bpf_jit_disasm: $(OUTPUT)bpf_jit_disasm.o $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ -lopcodes -lbfd -ldl $(OUTPUT)bpf_dbg: $(OUTPUT)bpf_dbg.o $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ -lreadline $(OUTPUT)bpf_asm: $(OUTPUT)bpf_asm.o $(OUTPUT)bpf_exp.yacc.o $(OUTPUT)bpf_exp.lex.o $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^ $(OUTPUT)bpf_exp.lex.c: $(OUTPUT)bpf_exp.yacc.c $(OUTPUT)bpf_exp.yacc.o: $(OUTPUT)bpf_exp.yacc.c $(OUTPUT)bpf_exp.lex.o: $(OUTPUT)bpf_exp.lex.c clean: bpftool_clean $(call QUIET_CLEAN, bpf-progs) $(Q)$(RM) -r -- $(OUTPUT)*.o $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg \ $(OUTPUT)bpf_asm $(OUTPUT)bpf_exp.yacc.* $(OUTPUT)bpf_exp.lex.* $(call QUIET_CLEAN, core-gen) $(Q)$(RM) -- $(OUTPUT)FEATURE-DUMP.bpf $(Q)$(RM) -r -- $(OUTPUT)feature install: $(PROGS) bpftool_install $(call QUIET_INSTALL, bpf_jit_disasm) $(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/bin $(Q)$(INSTALL) $(OUTPUT)bpf_jit_disasm $(DESTDIR)$(prefix)/bin/bpf_jit_disasm $(call QUIET_INSTALL, bpf_dbg) $(Q)$(INSTALL) $(OUTPUT)bpf_dbg $(DESTDIR)$(prefix)/bin/bpf_dbg $(call QUIET_INSTALL, bpf_asm) $(Q)$(INSTALL) $(OUTPUT)bpf_asm $(DESTDIR)$(prefix)/bin/bpf_asm bpftool: $(call descend,bpftool) bpftool_install: $(call descend,bpftool,install) bpftool_clean: $(call descend,bpftool,clean) .PHONY: all install clean bpftool bpftool_install bpftool_clean test_cgrp2_sock2.sh 0000755 00000003026 14722070530 0010261 0 ustar 00 #!/bin/bash # SPDX-License-Identifier: GPL-2.0 function config_device { ip netns add at_ns0 ip link add veth0 type veth peer name veth0b ip link set veth0b up ip link set veth0 netns at_ns0 ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth0 ip netns exec at_ns0 ip addr add 2401:db00::1/64 dev veth0 nodad ip netns exec at_ns0 ip link set dev veth0 up ip addr add 172.16.1.101/24 dev veth0b ip addr add 2401:db00::2/64 dev veth0b nodad } function config_cgroup { rm -rf /tmp/cgroupv2 mkdir -p /tmp/cgroupv2 mount -t cgroup2 none /tmp/cgroupv2 mkdir -p /tmp/cgroupv2/foo echo $$ >> /tmp/cgroupv2/foo/cgroup.procs } function attach_bpf { test_cgrp2_sock2 /tmp/cgroupv2/foo sock_flags_kern.o $1 [ $? -ne 0 ] && exit 1 } function cleanup { if [ -d /tmp/cgroupv2/foo ]; then test_cgrp2_sock -d /tmp/cgroupv2/foo fi ip link del veth0b ip netns delete at_ns0 umount /tmp/cgroupv2 rm -rf /tmp/cgroupv2 } cleanup 2>/dev/null set -e config_device config_cgroup set +e # # Test 1 - fail ping6 # attach_bpf 0 ping -c1 -w1 172.16.1.100 if [ $? -ne 0 ]; then echo "ping failed when it should succeed" cleanup exit 1 fi ping6 -c1 -w1 2401:db00::1 if [ $? -eq 0 ]; then echo "ping6 succeeded when it should not" cleanup exit 1 fi # # Test 2 - fail ping # attach_bpf 1 ping6 -c1 -w1 2401:db00::1 if [ $? -ne 0 ]; then echo "ping6 failed when it should succeed" cleanup exit 1 fi ping -c1 -w1 172.16.1.100 if [ $? -eq 0 ]; then echo "ping succeeded when it should not" cleanup exit 1 fi cleanup echo echo "*** PASS ***" test_cgrp2_tc.sh 0000755 00000010236 14722070530 0007647 0 ustar 00 #!/bin/bash # SPDX-License-Identifier: GPL-2.0 MY_DIR=$(dirname $0) # Details on the bpf prog BPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin' BPF_PROG="$MY_DIR/test_cgrp2_tc_kern.o" BPF_SECTION='filter' [ -z "$TC" ] && TC='tc' [ -z "$IP" ] && IP='ip' # Names of the veth interface, net namespace...etc. HOST_IFC='ve' NS_IFC='vens' NS='ns' find_mnt() { cat /proc/mounts | \ awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }' } # Init cgroup2 vars init_cgrp2_vars() { CGRP2_ROOT=$(find_mnt cgroup2) if [ -z "$CGRP2_ROOT" ] then CGRP2_ROOT='/mnt/cgroup2' MOUNT_CGRP2="yes" fi CGRP2_TC="$CGRP2_ROOT/tc" CGRP2_TC_LEAF="$CGRP2_TC/leaf" } # Init bpf fs vars init_bpf_fs_vars() { local bpf_fs_root=$(find_mnt bpf) [ -n "$bpf_fs_root" ] || return -1 BPF_FS_TC_SHARE="$bpf_fs_root/tc/globals" } setup_cgrp2() { case $1 in start) if [ "$MOUNT_CGRP2" == 'yes' ] then [ -d $CGRP2_ROOT ] || mkdir -p $CGRP2_ROOT mount -t cgroup2 none $CGRP2_ROOT || return $? fi mkdir -p $CGRP2_TC_LEAF ;; *) rmdir $CGRP2_TC_LEAF && rmdir $CGRP2_TC [ "$MOUNT_CGRP2" == 'yes' ] && umount $CGRP2_ROOT ;; esac } setup_bpf_cgrp2_array() { local bpf_cgrp2_array="$BPF_FS_TC_SHARE/$BPF_CGRP2_ARRAY_NAME" case $1 in start) $MY_DIR/test_cgrp2_array_pin -U $bpf_cgrp2_array -v $CGRP2_TC ;; *) [ -d "$BPF_FS_TC_SHARE" ] && rm -f $bpf_cgrp2_array ;; esac } setup_net() { case $1 in start) $IP link add $HOST_IFC type veth peer name $NS_IFC || return $? $IP link set dev $HOST_IFC up || return $? sysctl -q net.ipv6.conf.$HOST_IFC.accept_dad=0 $IP netns add ns || return $? $IP link set dev $NS_IFC netns ns || return $? $IP -n $NS link set dev $NS_IFC up || return $? $IP netns exec $NS sysctl -q net.ipv6.conf.$NS_IFC.accept_dad=0 $TC qdisc add dev $HOST_IFC clsact || return $? $TC filter add dev $HOST_IFC egress bpf da obj $BPF_PROG sec $BPF_SECTION || return $? ;; *) $IP netns del $NS $IP link del $HOST_IFC ;; esac } run_in_cgrp() { # Fork another bash and move it under the specified cgroup. # It makes the cgroup cleanup easier at the end of the test. cmd='echo $$ > ' cmd="$cmd $1/cgroup.procs; exec $2" bash -c "$cmd" } do_test() { run_in_cgrp $CGRP2_TC_LEAF "ping -6 -c3 ff02::1%$HOST_IFC >& /dev/null" local dropped=$($TC -s qdisc show dev $HOST_IFC | tail -3 | \ awk '/drop/{print substr($7, 0, index($7, ",")-1)}') if [[ $dropped -eq 0 ]] then echo "FAIL" return 1 else echo "Successfully filtered $dropped packets" return 0 fi } do_exit() { if [ "$DEBUG" == "yes" ] && [ "$MODE" != 'cleanuponly' ] then echo "------ DEBUG ------" echo "mount: "; mount | egrep '(cgroup2|bpf)'; echo echo "$CGRP2_TC_LEAF: "; ls -l $CGRP2_TC_LEAF; echo if [ -d "$BPF_FS_TC_SHARE" ] then echo "$BPF_FS_TC_SHARE: "; ls -l $BPF_FS_TC_SHARE; echo fi echo "Host net:" $IP netns $IP link show dev $HOST_IFC $IP -6 a show dev $HOST_IFC $TC -s qdisc show dev $HOST_IFC echo echo "$NS net:" $IP -n $NS link show dev $NS_IFC $IP -n $NS -6 link show dev $NS_IFC echo "------ DEBUG ------" echo fi if [ "$MODE" != 'nocleanup' ] then setup_net stop setup_bpf_cgrp2_array stop setup_cgrp2 stop fi } init_cgrp2_vars init_bpf_fs_vars while [[ $# -ge 1 ]] do a="$1" case $a in debug) DEBUG='yes' shift 1 ;; cleanup-only) MODE='cleanuponly' shift 1 ;; no-cleanup) MODE='nocleanup' shift 1 ;; *) echo "test_cgrp2_tc [debug] [cleanup-only | no-cleanup]" echo " debug: Print cgrp and network setup details at the end of the test" echo " cleanup-only: Try to cleanup things from last test. No test will be run" echo " no-cleanup: Run the test but don't do cleanup at the end" echo "[Note: If no arg is given, it will run the test and do cleanup at the end]" echo exit -1 ;; esac done trap do_exit 0 [ "$MODE" == 'cleanuponly' ] && exit setup_cgrp2 start || exit $? setup_net start || exit $? init_bpf_fs_vars || exit $? setup_bpf_cgrp2_array start || exit $? do_test echo do_hbm_test.sh 0000755 00000030105 14722070530 0007371 0 ustar 00 #!/bin/bash # SPDX-License-Identifier: GPL-2.0 # # Copyright (c) 2019 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. Usage() { echo "Script for testing HBM (Host Bandwidth Manager) framework." echo "It creates a cgroup to use for testing and load a BPF program to limit" echo "egress or ingress bandwidht. It then uses iperf3 or netperf to create" echo "loads. The output is the goodput in Mbps (unless -D was used)." echo "" echo "USAGE: $name [out] [-b=<prog>|--bpf=<prog>] [-c=<cc>|--cc=<cc>]" echo " [-D] [-d=<delay>|--delay=<delay>] [--debug] [-E] [--edt]" echo " [-f=<#flows>|--flows=<#flows>] [-h] [-i=<id>|--id=<id >]" echo " [-l] [-N] [--no_cn] [-p=<port>|--port=<port>] [-P]" echo " [-q=<qdisc>] [-R] [-s=<server>|--server=<server]" echo " [-S|--stats] -t=<time>|--time=<time>] [-w] [cubic|dctcp]" echo " Where:" echo " out egress (default)" echo " -b or --bpf BPF program filename to load and attach." echo " Default is hbm_out_kern.o for egress," echo " -c or -cc TCP congestion control (cubic or dctcp)" echo " --debug print BPF trace buffer" echo " -d or --delay add a delay in ms using netem" echo " -D In addition to the goodput in Mbps, it also outputs" echo " other detailed information. This information is" echo " test dependent (i.e. iperf3 or netperf)." echo " -E enable ECN (not required for dctcp)" echo " --edt use fq's Earliest Departure Time (requires fq)" echo " -f or --flows number of concurrent flows (default=1)" echo " -i or --id cgroup id (an integer, default is 1)" echo " -N use netperf instead of iperf3" echo " --no_cn Do not return CN notifications" echo " -l do not limit flows using loopback" echo " -h Help" echo " -p or --port iperf3 port (default is 5201)" echo " -P use an iperf3 instance for each flow" echo " -q use the specified qdisc" echo " -r or --rate rate in Mbps (default 1s 1Gbps)" echo " -R Use TCP_RR for netperf. 1st flow has req" echo " size of 10KB, rest of 1MB. Reply in all" echo " cases is 1 byte." echo " More detailed output for each flow can be found" echo " in the files netperf.<cg>.<flow>, where <cg> is the" echo " cgroup id as specified with the -i flag, and <flow>" echo " is the flow id starting at 1 and increasing by 1 for" echo " flow (as specified by -f)." echo " -s or --server hostname of netperf server. Used to create netperf" echo " test traffic between to hosts (default is within host)" echo " netserver must be running on the host." echo " -S or --stats whether to update hbm stats (default is yes)." echo " -t or --time duration of iperf3 in seconds (default=5)" echo " -w Work conserving flag. cgroup can increase its" echo " bandwidth beyond the rate limit specified" echo " while there is available bandwidth. Current" echo " implementation assumes there is only one NIC" echo " (eth0), but can be extended to support multiple" echo " NICs." echo " cubic or dctcp specify which TCP CC to use" echo " " exit } #set -x debug_flag=0 args="$@" name="$0" netem=0 cc=x dir="-o" dir_name="out" dur=5 flows=1 id=1 prog="" port=5201 rate=1000 multi_iperf=0 flow_cnt=1 use_netperf=0 rr=0 ecn=0 details=0 server="" qdisc="" flags="" do_stats=0 function start_hbm () { rm -f hbm.out echo "./hbm $dir -n $id -r $rate -t $dur $flags $dbg $prog" > hbm.out echo " " >> hbm.out ./hbm $dir -n $id -r $rate -t $dur $flags $dbg $prog >> hbm.out 2>&1 & echo $! } processArgs () { for i in $args ; do case $i in # Support for upcomming ingress rate limiting #in) # support for upcoming ingress rate limiting # dir="-i" # dir_name="in" # ;; out) dir="-o" dir_name="out" ;; -b=*|--bpf=*) prog="${i#*=}" ;; -c=*|--cc=*) cc="${i#*=}" ;; --no_cn) flags="$flags --no_cn" ;; --debug) flags="$flags -d" debug_flag=1 ;; -d=*|--delay=*) netem="${i#*=}" ;; -D) details=1 ;; -E) ecn=1 ;; --edt) flags="$flags --edt" qdisc="fq" ;; -f=*|--flows=*) flows="${i#*=}" ;; -i=*|--id=*) id="${i#*=}" ;; -l) flags="$flags -l" ;; -N) use_netperf=1 ;; -p=*|--port=*) port="${i#*=}" ;; -P) multi_iperf=1 ;; -q=*) qdisc="${i#*=}" ;; -r=*|--rate=*) rate="${i#*=}" ;; -R) rr=1 ;; -s=*|--server=*) server="${i#*=}" ;; -S|--stats) flags="$flags -s" do_stats=1 ;; -t=*|--time=*) dur="${i#*=}" ;; -w) flags="$flags -w" ;; cubic) cc=cubic ;; dctcp) cc=dctcp ;; *) echo "Unknown arg:$i" Usage ;; esac done } processArgs if [ $debug_flag -eq 1 ] ; then rm -f hbm_out.log fi hbm_pid=$(start_hbm) usleep 100000 host=`hostname` cg_base_dir=/sys/fs/cgroup cg_dir="$cg_base_dir/cgroup-test-work-dir/hbm$id" echo $$ >> $cg_dir/cgroup.procs ulimit -l unlimited rm -f ss.out rm -f hbm.[0-9]*.$dir_name if [ $ecn -ne 0 ] ; then sysctl -w -q -n net.ipv4.tcp_ecn=1 fi if [ $use_netperf -eq 0 ] ; then cur_cc=`sysctl -n net.ipv4.tcp_congestion_control` if [ "$cc" != "x" ] ; then sysctl -w -q -n net.ipv4.tcp_congestion_control=$cc fi fi if [ "$netem" -ne "0" ] ; then if [ "$qdisc" != "" ] ; then echo "WARNING: Ignoring -q options because -d option used" fi tc qdisc del dev lo root > /dev/null 2>&1 tc qdisc add dev lo root netem delay $netem\ms > /dev/null 2>&1 elif [ "$qdisc" != "" ] ; then tc qdisc del dev eth0 root > /dev/null 2>&1 tc qdisc add dev eth0 root $qdisc > /dev/null 2>&1 fi n=0 m=$[$dur * 5] hn="::1" if [ $use_netperf -ne 0 ] ; then if [ "$server" != "" ] ; then hn=$server fi fi ( ping6 -i 0.2 -c $m $hn > ping.out 2>&1 ) & if [ $use_netperf -ne 0 ] ; then begNetserverPid=`ps ax | grep netserver | grep --invert-match "grep" | \ awk '{ print $1 }'` if [ "$begNetserverPid" == "" ] ; then if [ "$server" == "" ] ; then ( ./netserver > /dev/null 2>&1) & usleep 100000 fi fi flow_cnt=1 if [ "$server" == "" ] ; then np_server=$host else np_server=$server fi if [ "$cc" == "x" ] ; then np_cc="" else np_cc="-K $cc,$cc" fi replySize=1 while [ $flow_cnt -le $flows ] ; do if [ $rr -ne 0 ] ; then reqSize=1M if [ $flow_cnt -eq 1 ] ; then reqSize=10K fi if [ "$dir" == "-i" ] ; then replySize=$reqSize reqSize=1 fi ( ./netperf -H $np_server -l $dur -f m -j -t TCP_RR -- -r $reqSize,$replySize $np_cc -k P50_lATENCY,P90_LATENCY,LOCAL_TRANSPORT_RETRANS,REMOTE_TRANSPORT_RETRANS,LOCAL_SEND_THROUGHPUT,LOCAL_RECV_THROUGHPUT,REQUEST_SIZE,RESPONSE_SIZE > netperf.$id.$flow_cnt ) & else if [ "$dir" == "-i" ] ; then ( ./netperf -H $np_server -l $dur -f m -j -t TCP_RR -- -r 1,10M $np_cc -k P50_LATENCY,P90_LATENCY,LOCAL_TRANSPORT_RETRANS,LOCAL_SEND_THROUGHPUT,REMOTE_TRANSPORT_RETRANS,REMOTE_SEND_THROUGHPUT,REQUEST_SIZE,RESPONSE_SIZE > netperf.$id.$flow_cnt ) & else ( ./netperf -H $np_server -l $dur -f m -j -t TCP_STREAM -- $np_cc -k P50_lATENCY,P90_LATENCY,LOCAL_TRANSPORT_RETRANS,LOCAL_SEND_THROUGHPUT,REQUEST_SIZE,RESPONSE_SIZE > netperf.$id.$flow_cnt ) & fi fi flow_cnt=$[flow_cnt+1] done # sleep for duration of test (plus some buffer) n=$[dur+2] sleep $n # force graceful termination of netperf pids=`pgrep netperf` for p in $pids ; do kill -SIGALRM $p done flow_cnt=1 rate=0 if [ $details -ne 0 ] ; then echo "" echo "Details for HBM in cgroup $id" if [ $do_stats -eq 1 ] ; then if [ -e hbm.$id.$dir_name ] ; then cat hbm.$id.$dir_name fi fi fi while [ $flow_cnt -le $flows ] ; do if [ "$dir" == "-i" ] ; then r=`cat netperf.$id.$flow_cnt | grep -o "REMOTE_SEND_THROUGHPUT=[0-9]*" | grep -o "[0-9]*"` else r=`cat netperf.$id.$flow_cnt | grep -o "LOCAL_SEND_THROUGHPUT=[0-9]*" | grep -o "[0-9]*"` fi echo "rate for flow $flow_cnt: $r" rate=$[rate+r] if [ $details -ne 0 ] ; then echo "-----" echo "Details for cgroup $id, flow $flow_cnt" cat netperf.$id.$flow_cnt fi flow_cnt=$[flow_cnt+1] done if [ $details -ne 0 ] ; then echo "" delay=`grep "avg" ping.out | grep -o "= [0-9.]*/[0-9.]*" | grep -o "[0-9.]*$"` echo "PING AVG DELAY:$delay" echo "AGGREGATE_GOODPUT:$rate" else echo $rate fi elif [ $multi_iperf -eq 0 ] ; then (iperf3 -s -p $port -1 > /dev/null 2>&1) & usleep 100000 iperf3 -c $host -p $port -i 0 -P $flows -f m -t $dur > iperf.$id rates=`grep receiver iperf.$id | grep -o "[0-9.]* Mbits" | grep -o "^[0-9]*"` rate=`echo $rates | grep -o "[0-9]*$"` if [ $details -ne 0 ] ; then echo "" echo "Details for HBM in cgroup $id" if [ $do_stats -eq 1 ] ; then if [ -e hbm.$id.$dir_name ] ; then cat hbm.$id.$dir_name fi fi delay=`grep "avg" ping.out | grep -o "= [0-9.]*/[0-9.]*" | grep -o "[0-9.]*$"` echo "PING AVG DELAY:$delay" echo "AGGREGATE_GOODPUT:$rate" else echo $rate fi else flow_cnt=1 while [ $flow_cnt -le $flows ] ; do (iperf3 -s -p $port -1 > /dev/null 2>&1) & ( iperf3 -c $host -p $port -i 0 -P 1 -f m -t $dur | grep receiver | grep -o "[0-9.]* Mbits" | grep -o "^[0-9]*" | grep -o "[0-9]*$" > iperf3.$id.$flow_cnt ) & port=$[port+1] flow_cnt=$[flow_cnt+1] done n=$[dur+1] sleep $n flow_cnt=1 rate=0 if [ $details -ne 0 ] ; then echo "" echo "Details for HBM in cgroup $id" if [ $do_stats -eq 1 ] ; then if [ -e hbm.$id.$dir_name ] ; then cat hbm.$id.$dir_name fi fi fi while [ $flow_cnt -le $flows ] ; do r=`cat iperf3.$id.$flow_cnt` # echo "rate for flow $flow_cnt: $r" if [ $details -ne 0 ] ; then echo "Rate for cgroup $id, flow $flow_cnt LOCAL_SEND_THROUGHPUT=$r" fi rate=$[rate+r] flow_cnt=$[flow_cnt+1] done if [ $details -ne 0 ] ; then delay=`grep "avg" ping.out | grep -o "= [0-9.]*/[0-9.]*" | grep -o "[0-9.]*$"` echo "PING AVG DELAY:$delay" echo "AGGREGATE_GOODPUT:$rate" else echo $rate fi fi if [ $use_netperf -eq 0 ] ; then sysctl -w -q -n net.ipv4.tcp_congestion_control=$cur_cc fi if [ $ecn -ne 0 ] ; then sysctl -w -q -n net.ipv4.tcp_ecn=0 fi if [ "$netem" -ne "0" ] ; then tc qdisc del dev lo root > /dev/null 2>&1 fi if [ "$qdisc" != "" ] ; then tc qdisc del dev eth0 root > /dev/null 2>&1 fi sleep 2 hbmPid=`ps ax | grep "hbm " | grep --invert-match "grep" | awk '{ print $1 }'` if [ "$hbmPid" == "$hbm_pid" ] ; then kill $hbm_pid fi sleep 1 # Detach any BPF programs that may have lingered ttx=`bpftool cgroup tree | grep hbm` v=2 for x in $ttx ; do if [ "${x:0:36}" == "/sys/fs/cgroup/cgroup-test-work-dir/" ] ; then cg=$x ; v=0 else if [ $v -eq 0 ] ; then id=$x ; v=1 else if [ $v -eq 1 ] ; then type=$x ; bpftool cgroup detach $cg $type id $id v=0 fi fi fi done if [ $use_netperf -ne 0 ] ; then if [ "$server" == "" ] ; then if [ "$begNetserverPid" == "" ] ; then netserverPid=`ps ax | grep netserver | grep --invert-match "grep" | awk '{ print $1 }'` if [ "$netserverPid" != "" ] ; then kill $netserverPid fi fi fi fi exit Makefile.helpers 0000644 00000003011 14722072313 0007641 0 ustar 00 # SPDX-License-Identifier: GPL-2.0-only ifndef allow-override include ../scripts/Makefile.include include ../scripts/utilities.mak else # Assume Makefile.helpers is being run from bpftool/Documentation # subdirectory. Go up two more directories to fetch bpf.h header and # associated script. UP2DIR := ../../ endif INSTALL ?= install RM ?= rm -f RMDIR ?= rmdir --ignore-fail-on-non-empty ifeq ($(V),1) Q = else Q = @ endif prefix ?= /usr/local mandir ?= $(prefix)/man man7dir = $(mandir)/man7 HELPERS_RST = bpf-helpers.rst MAN7_RST = $(HELPERS_RST) _DOC_MAN7 = $(patsubst %.rst,%.7,$(MAN7_RST)) DOC_MAN7 = $(addprefix $(OUTPUT),$(_DOC_MAN7)) helpers: man7 man7: $(DOC_MAN7) RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null) $(OUTPUT)$(HELPERS_RST): $(UP2DIR)../../include/uapi/linux/bpf.h $(QUIET_GEN)$(UP2DIR)../../scripts/bpf_helpers_doc.py --filename $< > $@ $(OUTPUT)%.7: $(OUTPUT)%.rst ifndef RST2MAN_DEP $(error "rst2man not found, but required to generate man pages") endif $(QUIET_GEN)rst2man $< > $@ helpers-clean: $(call QUIET_CLEAN, eBPF_helpers-manpage) $(Q)$(RM) $(DOC_MAN7) $(OUTPUT)$(HELPERS_RST) helpers-install: helpers $(call QUIET_INSTALL, eBPF_helpers-manpage) $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(man7dir) $(Q)$(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir) helpers-uninstall: $(call QUIET_UNINST, eBPF_helpers-manpage) $(Q)$(RM) $(addprefix $(DESTDIR)$(man7dir)/,$(_DOC_MAN7)) $(Q)$(RMDIR) $(DESTDIR)$(man7dir) .PHONY: helpers helpers-clean helpers-install helpers-uninstall bpftool/Makefile 0000644 00000007711 14722072313 0007660 0 ustar 00 # SPDX-License-Identifier: GPL-2.0-only include ../../scripts/Makefile.include ifeq ($(srctree),) srctree := $(patsubst %/,%,$(dir $(CURDIR))) srctree := $(patsubst %/,%,$(dir $(srctree))) srctree := $(patsubst %/,%,$(dir $(srctree))) endif ifeq ($(V),1) Q = else Q = @ endif BPF_DIR = $(srctree)/tools/lib/bpf/ ifneq ($(OUTPUT),) LIBBPF_OUTPUT = $(OUTPUT)/libbpf/ LIBBPF_PATH = $(LIBBPF_OUTPUT) else LIBBPF_PATH = $(BPF_DIR) endif LIBBPF = $(LIBBPF_PATH)libbpf.a BPFTOOL_VERSION := $(shell make -rR --no-print-directory -sC ../../.. kernelversion) $(LIBBPF): FORCE $(if $(LIBBPF_OUTPUT),@mkdir -p $(LIBBPF_OUTPUT)) $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_OUTPUT) $(LIBBPF_OUTPUT)libbpf.a $(LIBBPF)-clean: $(call QUIET_CLEAN, libbpf) $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_OUTPUT) clean >/dev/null prefix ?= /usr/local bash_compdir ?= /usr/share/bash-completion/completions CFLAGS += -O2 CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers CFLAGS += $(filter-out -Wswitch-enum,$(EXTRA_WARNINGS)) CFLAGS += -DPACKAGE='"bpftool"' -D__EXPORTED_HEADERS__ \ -I$(srctree)/kernel/bpf/ \ -I$(srctree)/tools/include \ -I$(srctree)/tools/include/uapi \ -I$(srctree)/tools/lib/bpf \ -I$(srctree)/tools/perf CFLAGS += -DBPFTOOL_VERSION='"$(BPFTOOL_VERSION)"' ifneq ($(EXTRA_CFLAGS),) CFLAGS += $(EXTRA_CFLAGS) endif ifneq ($(EXTRA_LDFLAGS),) LDFLAGS += $(EXTRA_LDFLAGS) endif LIBS = $(LIBBPF) -lelf -lz INSTALL ?= install RM ?= rm -f FEATURE_USER = .bpftool FEATURE_TESTS = libbfd disassembler-four-args reallocarray zlib FEATURE_DISPLAY = libbfd disassembler-four-args zlib check_feat := 1 NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall ifdef MAKECMDGOALS ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),) check_feat := 0 endif endif ifeq ($(check_feat),1) ifeq ($(FEATURES_DUMP),) include $(srctree)/tools/build/Makefile.feature else include $(FEATURES_DUMP) endif endif ifeq ($(feature-disassembler-four-args), 1) CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE endif ifeq ($(feature-reallocarray), 0) CFLAGS += -DCOMPAT_NEED_REALLOCARRAY endif include $(wildcard $(OUTPUT)*.d) all: $(OUTPUT)bpftool BFD_SRCS = jit_disasm.c SRCS = $(filter-out $(BFD_SRCS),$(wildcard *.c)) ifeq ($(feature-libbfd),1) LIBS += -lbfd -ldl -lopcodes else ifeq ($(feature-libbfd-liberty),1) LIBS += -lbfd -ldl -lopcodes -liberty else ifeq ($(feature-libbfd-liberty-z),1) LIBS += -lbfd -ldl -lopcodes -liberty -lz endif ifneq ($(filter -lbfd,$(LIBS)),) CFLAGS += -DHAVE_LIBBFD_SUPPORT SRCS += $(BFD_SRCS) endif OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o $(OUTPUT)disasm.o: $(srctree)/kernel/bpf/disasm.c $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $< $(OUTPUT)feature.o: | zdep $(OUTPUT)bpftool: $(OBJS) $(LIBBPF) $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(OUTPUT)%.o: %.c $(QUIET_CC)$(COMPILE.c) -MMD -o $@ $< clean: $(LIBBPF)-clean $(call QUIET_CLEAN, bpftool) $(Q)$(RM) -- $(OUTPUT)bpftool $(OUTPUT)*.o $(OUTPUT)*.d $(Q)$(RM) -r -- $(OUTPUT)libbpf/ $(call QUIET_CLEAN, core-gen) $(Q)$(RM) -- $(OUTPUT)FEATURE-DUMP.bpftool $(Q)$(RM) -r -- $(OUTPUT)feature/ install: $(OUTPUT)bpftool $(call QUIET_INSTALL, bpftool) $(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/sbin $(Q)$(INSTALL) $(OUTPUT)bpftool $(DESTDIR)$(prefix)/sbin/bpftool $(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(bash_compdir) $(Q)$(INSTALL) -m 0644 bash-completion/bpftool $(DESTDIR)$(bash_compdir) uninstall: $(call QUIET_UNINST, bpftool) $(Q)$(RM) -- $(DESTDIR)$(prefix)/sbin/bpftool $(Q)$(RM) -- $(DESTDIR)$(bash_compdir)/bpftool doc: $(call descend,Documentation) doc-clean: $(call descend,Documentation,clean) doc-install: $(call descend,Documentation,install) doc-uninstall: $(call descend,Documentation,uninstall) FORCE: zdep: @if [ "$(feature-zlib)" != "1" ]; then echo "No zlib found"; exit 1 ; fi .PHONY: all FORCE clean install uninstall zdep .PHONY: doc doc-clean doc-install doc-uninstall .DEFAULT_GOAL := all bpftool/Documentation/Makefile 0000644 00000002305 14722072313 0012463 0 ustar 00 # SPDX-License-Identifier: GPL-2.0-only include ../../../scripts/Makefile.include INSTALL ?= install RM ?= rm -f RMDIR ?= rmdir --ignore-fail-on-non-empty ifeq ($(V),1) Q = else Q = @ endif prefix ?= /usr/local mandir ?= $(prefix)/man man8dir = $(mandir)/man8 # Load targets for building eBPF helpers man page. include ../../Makefile.helpers MAN8_RST = $(filter-out $(HELPERS_RST),$(wildcard *.rst)) _DOC_MAN8 = $(patsubst %.rst,%.8,$(MAN8_RST)) DOC_MAN8 = $(addprefix $(OUTPUT),$(_DOC_MAN8)) man: man8 helpers man8: $(DOC_MAN8) RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null) $(OUTPUT)%.8: %.rst ifndef RST2MAN_DEP $(error "rst2man not found, but required to generate man pages") endif $(QUIET_GEN)rst2man $< > $@ clean: helpers-clean $(call QUIET_CLEAN, Documentation) $(Q)$(RM) $(DOC_MAN8) install: man helpers-install $(call QUIET_INSTALL, Documentation-man) $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(man8dir) $(Q)$(INSTALL) -m 644 $(DOC_MAN8) $(DESTDIR)$(man8dir) uninstall: helpers-uninstall $(call QUIET_UNINST, Documentation-man) $(Q)$(RM) $(addprefix $(DESTDIR)$(man8dir)/,$(_DOC_MAN8)) $(Q)$(RMDIR) $(DESTDIR)$(man8dir) .PHONY: man man8 clean install uninstall .DEFAULT_GOAL := man
| ver. 1.4 |
Github
|
.
| PHP 7.4.3-4ubuntu2.24 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка