0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 BPF_FILE=xdp2skb_meta_kern.o
0017 DIR=$(dirname $0)
0018
0019 [ -z "$TC" ] && TC=tc
0020 [ -z "$IP" ] && IP=ip
0021
0022 function usage() {
0023 echo ""
0024 echo "Usage: $0 [-vfh] --dev ethX"
0025 echo " -d | --dev : Network device (required)"
0026 echo " --flush : Cleanup flush TC and XDP progs"
0027 echo " --list : (\$LIST) List TC and XDP progs"
0028 echo " -v | --verbose : (\$VERBOSE) Verbose"
0029 echo " --dry-run : (\$DRYRUN) Dry-run only (echo commands)"
0030 echo ""
0031 }
0032
0033
0034 function err() {
0035 local exitcode=$1
0036 shift
0037 echo "ERROR: $@" >&2
0038 exit $exitcode
0039 }
0040
0041 function info() {
0042 if [[ -n "$VERBOSE" ]]; then
0043 echo "# $@"
0044 fi
0045 }
0046
0047
0048
0049
0050
0051 function _call_cmd() {
0052 local cmd="$1"
0053 local allow_fail="$2"
0054 shift 2
0055 if [[ -n "$VERBOSE" ]]; then
0056 echo "$cmd $@"
0057 fi
0058 if [[ -n "$DRYRUN" ]]; then
0059 return
0060 fi
0061 $cmd "$@"
0062 local status=$?
0063 if (( $status != 0 )); then
0064 if [[ "$allow_fail" == "" ]]; then
0065 err 2 "Exec error($status) occurred cmd: \"$cmd $@\""
0066 fi
0067 fi
0068 }
0069 function call_tc() {
0070 _call_cmd "$TC" "" "$@"
0071 }
0072 function call_tc_allow_fail() {
0073 _call_cmd "$TC" "allow_fail" "$@"
0074 }
0075 function call_ip() {
0076 _call_cmd "$IP" "" "$@"
0077 }
0078
0079
0080
0081 OPTIONS=$(getopt -o vfhd: \
0082 --long verbose,flush,help,list,dev:,dry-run -- "$@")
0083 if (( $? != 0 )); then
0084 err 4 "Error calling getopt"
0085 fi
0086 eval set -- "$OPTIONS"
0087
0088 unset DEV
0089 unset FLUSH
0090 while true; do
0091 case "$1" in
0092 -d | --dev )
0093 DEV=$2
0094 info "Device set to: DEV=$DEV" >&2
0095 shift 2
0096 ;;
0097 -v | --verbose)
0098 VERBOSE=yes
0099
0100 shift
0101 ;;
0102 --dry-run )
0103 DRYRUN=yes
0104 VERBOSE=yes
0105 info "Dry-run mode: enable VERBOSE and don't call TC+IP" >&2
0106 shift
0107 ;;
0108 -f | --flush )
0109 FLUSH=yes
0110 shift
0111 ;;
0112 --list )
0113 LIST=yes
0114 shift
0115 ;;
0116 -- )
0117 shift
0118 break
0119 ;;
0120 -h | --help )
0121 usage;
0122 exit 0
0123 ;;
0124 * )
0125 shift
0126 break
0127 ;;
0128 esac
0129 done
0130
0131 FILE="$DIR/$BPF_FILE"
0132 if [[ ! -e $FILE ]]; then
0133 err 3 "Missing BPF object file ($FILE)"
0134 fi
0135
0136 if [[ -z $DEV ]]; then
0137 usage
0138 err 2 "Please specify network device -- required option --dev"
0139 fi
0140
0141
0142
0143 function list_tc()
0144 {
0145 local device="$1"
0146 shift
0147 info "Listing current TC ingress rules"
0148 call_tc filter show dev $device ingress
0149 }
0150
0151 function list_xdp()
0152 {
0153 local device="$1"
0154 shift
0155 info "Listing current XDP device($device) setting"
0156 call_ip link show dev $device | grep --color=auto xdp
0157 }
0158
0159 function flush_tc()
0160 {
0161 local device="$1"
0162 shift
0163 info "Flush TC on device: $device"
0164 call_tc_allow_fail filter del dev $device ingress
0165 call_tc_allow_fail qdisc del dev $device clsact
0166 }
0167
0168 function flush_xdp()
0169 {
0170 local device="$1"
0171 shift
0172 info "Flush XDP on device: $device"
0173 call_ip link set dev $device xdp off
0174 }
0175
0176 function attach_tc_mark()
0177 {
0178 local device="$1"
0179 local file="$2"
0180 local prog="tc_mark"
0181 shift 2
0182
0183
0184 call_tc_allow_fail qdisc del dev $device clsact 2> /dev/null
0185 call_tc qdisc add dev $device clsact
0186
0187
0188 call_tc filter add dev $device ingress \
0189 prio 1 handle 1 bpf da obj $file sec $prog
0190 }
0191
0192 function attach_xdp_mark()
0193 {
0194 local device="$1"
0195 local file="$2"
0196 local prog="xdp_mark"
0197 shift 2
0198
0199
0200
0201 flush_xdp $device
0202
0203
0204 call_ip link set dev $device xdp obj $file sec $prog
0205 }
0206
0207 if [[ -n $FLUSH ]]; then
0208 flush_tc $DEV
0209 flush_xdp $DEV
0210 exit 0
0211 fi
0212
0213 if [[ -n $LIST ]]; then
0214 list_tc $DEV
0215 list_xdp $DEV
0216 exit 0
0217 fi
0218
0219 attach_tc_mark $DEV $FILE
0220 attach_xdp_mark $DEV $FILE