Commit | Line | Data |
---|---|---|
36e04a2d JDB |
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 | # | |
16 | BPF_FILE=xdp2skb_meta_kern.o | |
17 | DIR=$(dirname $0) | |
18 | ||
b9626f45 TS |
19 | [ -z "$TC" ] && TC=tc |
20 | [ -z "$IP" ] && IP=ip | |
36e04a2d JDB |
21 | |
22 | function 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 -- | |
34 | function err() { | |
35 | local exitcode=$1 | |
36 | shift | |
37 | echo "ERROR: $@" >&2 | |
38 | exit $exitcode | |
39 | } | |
40 | ||
41 | function 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 | |
51 | function _call_cmd() { | |
52 | local cmd="$1" | |
53 | local allow_fail="$2" | |
54 | shift 2 | |
55 | if [[ -n "$VERBOSE" ]]; then | |
b9626f45 | 56 | echo "$cmd $@" |
36e04a2d JDB |
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 | } | |
69 | function call_tc() { | |
70 | _call_cmd "$TC" "" "$@" | |
71 | } | |
72 | function call_tc_allow_fail() { | |
73 | _call_cmd "$TC" "allow_fail" "$@" | |
74 | } | |
75 | function call_ip() { | |
76 | _call_cmd "$IP" "" "$@" | |
77 | } | |
78 | ||
79 | ## --- Parse command line arguments / parameters --- | |
80 | # Using external program "getopt" to get --long-options | |
81 | OPTIONS=$(getopt -o vfhd: \ | |
82 | --long verbose,flush,help,list,dev:,dry-run -- "$@") | |
83 | if (( $? != 0 )); then | |
84 | err 4 "Error calling getopt" | |
85 | fi | |
86 | eval set -- "$OPTIONS" | |
87 | ||
88 | unset DEV | |
89 | unset FLUSH | |
90 | while 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 | |
129 | done | |
130 | ||
131 | FILE="$DIR/$BPF_FILE" | |
132 | if [[ ! -e $FILE ]]; then | |
133 | err 3 "Missing BPF object file ($FILE)" | |
134 | fi | |
135 | ||
136 | if [[ -z $DEV ]]; then | |
137 | usage | |
138 | err 2 "Please specify network device -- required option --dev" | |
139 | fi | |
140 | ||
141 | ## -- Function calls -- | |
142 | ||
143 | function 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 | ||
151 | function 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 | ||
159 | function 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 | ||
168 | function 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 | ||
176 | function 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 | ||
192 | function 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 | ||
207 | if [[ -n $FLUSH ]]; then | |
208 | flush_tc $DEV | |
209 | flush_xdp $DEV | |
210 | exit 0 | |
211 | fi | |
212 | ||
213 | if [[ -n $LIST ]]; then | |
214 | list_tc $DEV | |
215 | list_xdp $DEV | |
216 | exit 0 | |
217 | fi | |
218 | ||
219 | attach_tc_mark $DEV $FILE | |
220 | attach_xdp_mark $DEV $FILE |