linux/samples/bpf/xdp2skb_meta.sh
<<
>>
Prefs
   1#!/bin/bash
   2#
   3# SPDX-License-Identifier: GPL-2.0
   4# Copyright (c) 2018 Jesper Dangaard Brouer, Red Hat Inc.
   5#
   6# Bash-shell example on using iproute2 tools 'tc' and 'ip' to load
   7# eBPF programs, both for XDP and clsbpf.  Shell script function
   8# wrappers and even long options parsing is illustrated, for ease of
   9# use.
  10#
  11# Related to sample/bpf/xdp2skb_meta_kern.c, which contains BPF-progs
  12# that need to collaborate between XDP and TC hooks.  Thus, it is
  13# convenient that the same tool load both programs that need to work
  14# together.
  15#
  16BPF_FILE=xdp2skb_meta_kern.o
  17DIR=$(dirname $0)
  18
  19[ -z "$TC" ] && TC=tc
  20[ -z "$IP" ] && IP=ip
  21
  22function usage() {
  23    echo ""
  24    echo "Usage: $0 [-vfh] --dev ethX"
  25    echo "  -d | --dev     :             Network device (required)"
  26    echo "  --flush        :             Cleanup flush TC and XDP progs"
  27    echo "  --list         : (\$LIST)     List TC and XDP progs"
  28    echo "  -v | --verbose : (\$VERBOSE)  Verbose"
  29    echo "  --dry-run      : (\$DRYRUN)   Dry-run only (echo commands)"
  30    echo ""
  31}
  32
  33## -- General shell logging cmds --
  34function err() {
  35    local exitcode=$1
  36    shift
  37    echo "ERROR: $@" >&2
  38    exit $exitcode
  39}
  40
  41function info() {
  42    if [[ -n "$VERBOSE" ]]; then
  43        echo "# $@"
  44    fi
  45}
  46
  47## -- Helper function calls --
  48
  49# Wrapper call for TC and IP
  50# - Will display the offending command on failure
  51function _call_cmd() {
  52    local cmd="$1"
  53    local allow_fail="$2"
  54    shift 2
  55    if [[ -n "$VERBOSE" ]]; then
  56        echo "$cmd $@"
  57    fi
  58    if [[ -n "$DRYRUN" ]]; then
  59        return
  60    fi
  61    $cmd "$@"
  62    local status=$?
  63    if (( $status != 0 )); then
  64        if [[ "$allow_fail" == "" ]]; then
  65            err 2 "Exec error($status) occurred cmd: \"$cmd $@\""
  66        fi
  67    fi
  68}
  69function call_tc() {
  70    _call_cmd "$TC" "" "$@"
  71}
  72function call_tc_allow_fail() {
  73    _call_cmd "$TC" "allow_fail" "$@"
  74}
  75function call_ip() {
  76    _call_cmd "$IP" "" "$@"
  77}
  78
  79##  --- Parse command line arguments / parameters ---
  80# Using external program "getopt" to get --long-options
  81OPTIONS=$(getopt -o vfhd: \
  82    --long verbose,flush,help,list,dev:,dry-run -- "$@")
  83if (( $? != 0 )); then
  84    err 4 "Error calling getopt"
  85fi
  86eval set -- "$OPTIONS"
  87
  88unset DEV
  89unset FLUSH
  90while true; do
  91    case "$1" in
  92        -d | --dev ) # device
  93            DEV=$2
  94            info "Device set to: DEV=$DEV" >&2
  95            shift 2
  96            ;;
  97        -v | --verbose)
  98            VERBOSE=yes
  99            # info "Verbose mode: VERBOSE=$VERBOSE" >&2
 100            shift
 101            ;;
 102        --dry-run )
 103            DRYRUN=yes
 104            VERBOSE=yes
 105            info "Dry-run mode: enable VERBOSE and don't call TC+IP" >&2
 106            shift
 107            ;;
 108        -f | --flush )
 109            FLUSH=yes
 110            shift
 111            ;;
 112        --list )
 113            LIST=yes
 114            shift
 115            ;;
 116        -- )
 117            shift
 118            break
 119            ;;
 120        -h | --help )
 121            usage;
 122            exit 0
 123            ;;
 124        * )
 125            shift
 126            break
 127            ;;
 128    esac
 129done
 130
 131FILE="$DIR/$BPF_FILE"
 132if [[ ! -e $FILE ]]; then
 133    err 3 "Missing BPF object file ($FILE)"
 134fi
 135
 136if [[ -z $DEV ]]; then
 137    usage
 138    err 2 "Please specify network device -- required option --dev"
 139fi
 140
 141## -- Function calls --
 142
 143function list_tc()
 144{
 145    local device="$1"
 146    shift
 147    info "Listing current TC ingress rules"
 148    call_tc filter show dev $device ingress
 149}
 150
 151function list_xdp()
 152{
 153    local device="$1"
 154    shift
 155    info "Listing current XDP device($device) setting"
 156    call_ip link show dev $device | grep --color=auto xdp
 157}
 158
 159function flush_tc()
 160{
 161    local device="$1"
 162    shift
 163    info "Flush TC on device: $device"
 164    call_tc_allow_fail filter del dev $device ingress
 165    call_tc_allow_fail qdisc del dev $device clsact
 166}
 167
 168function flush_xdp()
 169{
 170    local device="$1"
 171    shift
 172    info "Flush XDP on device: $device"
 173    call_ip link set dev $device xdp off
 174}
 175
 176function attach_tc_mark()
 177{
 178    local device="$1"
 179    local file="$2"
 180    local prog="tc_mark"
 181    shift 2
 182
 183    # Re-attach clsact to clear/flush existing role
 184    call_tc_allow_fail qdisc del dev $device clsact 2> /dev/null
 185    call_tc            qdisc add dev $device clsact
 186
 187    # Attach BPF prog
 188    call_tc filter add dev $device ingress \
 189            prio 1 handle 1 bpf da obj $file sec $prog
 190}
 191
 192function attach_xdp_mark()
 193{
 194    local device="$1"
 195    local file="$2"
 196    local prog="xdp_mark"
 197    shift 2
 198
 199    # Remove XDP prog in-case it's already loaded
 200    # TODO: Need ip-link option to override/replace existing XDP prog
 201    flush_xdp $device
 202
 203    # Attach XDP/BPF prog
 204    call_ip link set dev $device xdp obj $file sec $prog
 205}
 206
 207if [[ -n $FLUSH ]]; then
 208    flush_tc  $DEV
 209    flush_xdp $DEV
 210    exit 0
 211fi
 212
 213if [[ -n $LIST ]]; then
 214    list_tc  $DEV
 215    list_xdp $DEV
 216    exit 0
 217fi
 218
 219attach_tc_mark  $DEV $FILE
 220attach_xdp_mark $DEV $FILE
 221