config.sh revision 0ee09439
1#! /bin/bash
2
3# hardcoded variables which can be changed by the user if needed---------------
4
5# DPDK port to be used
6DPDK_PORT=0
7
8# TCP port to be used
9TCP_PORT=6000
10
11# local interface addresses to set
12LOCAL_IPV4=192.168.1.60
13LOCAL_IPV6=fd12:3456:789a:0001:0000:0000:0000:0060
14
15# remote interface addresses to set
16REMOTE_IPV4=192.168.1.64
17REMOTE_IPV6=fd12:3456:789a:0001:0000:0000:0000:0064
18
19# mask length for addresses of each IP version
20MASK_IPV4=24
21MASK_IPV6=64
22
23# name of the config files for backend and frontend of l4fwd app
24L4FWD_BE_CFG_FILE=$(mktemp)
25L4FWD_FE_CFG_FILE=$(mktemp)
26
27# directory on remote to store tmp files - default /tmp/
28REMOTE_DIR=/tmp/l4fwd_test
29# directory on remote to store output files
30REMOTE_OUTDIR=${REMOTE_DIR}/out
31# directory on remote to store results
32REMOTE_RESDIR=${REMOTE_DIR}/results
33
34# checks done on environment variables-----------------------------------------
35
36# check ETH_DEV
37if [[ -z "${ETH_DEV}" ]]
38then
39	echo "ETH_DEV is invalid"
40	exit 127
41fi
42
43# check if L4FWD_PATH points to an executable
44if [[ ! -x ${L4FWD_PATH} ]]
45then
46	echo "${L4FWD_PATH} is not executable"
47	exit 127
48fi
49
50# check if REMOTE_HOST is reachable
51ssh ${REMOTE_HOST} echo
52st=$?
53if [[ $st -ne 0 ]]
54then
55	echo "host ${REMOTE_HOST} is not reachable"
56	exit $st
57fi
58
59# get ethernet address of REMOTE_HOST
60REMOTE_MAC=$(ssh ${REMOTE_HOST} ip addr show dev ${REMOTE_IFACE})
61st=$?
62REMOTE_MAC=$(echo ${REMOTE_MAC} | sed -e 's/^.*ether //' -e 's/ brd.*$//')
63if [[ $st -ne 0 || -z "${REMOTE_MAC}" ]]
64then
65	echo "could not retrive ethernet address from ${REMOTE_IFACE}"
66	exit 127
67fi
68
69# check if FECORE is set - default 0
70L4FWD_FECORE=${L4FWD_FECORE:-0}
71
72# check if BECORE is set - default FECORE
73L4FWD_BECORE=${L4FWD_BECORE:-${L4FWD_FECORE}}
74
75# l4fwd app settings-----------------------------------------------------------
76
77# set file for l4fwd app output
78L4FWD_OUT_FILE=./l4fwd.out
79# set rbufs/sbufs/streams to open for l4fwd
80L4FWD_STREAMS='--rbufs 0x100 --sbufs 0x100 --streams 0x100'
81
82# set lcores for DPDK to start
83if [[ ${L4FWD_FECORE} -ne ${L4FWD_BECORE} ]]
84then
85	L4FWD_LCORE="${L4FWD_FECORE},${L4FWD_BECORE}"
86else
87	L4FWD_LCORE="${L4FWD_FECORE}"
88fi
89
90# set EAL parameters
91L4FWD_CMD_EAL_PRM="--lcores='${L4FWD_LCORE}' -n 4 ${ETH_DEV}"
92
93# l4fwd parameters (listen, TCP only, enable arp, promiscuous)
94L4FWD_CMD_PRM="--listen --tcp --enable-arp --promisc ${L4FWD_STREAMS}"
95
96# l4fwd config files
97L4FWD_CONFIG="--fecfg ${L4FWD_FE_CFG_FILE} --becfg ${L4FWD_BE_CFG_FILE}"
98
99# port parameters
100if [[ ${ipv4} -eq 1 ]]
101then
102	L4FWD_PORT_PRM="port=${DPDK_PORT},lcore=${L4FWD_BECORE},rx_offload=0x0\
103,tx_offload=0x0,ipv4=${LOCAL_IPV4}"
104elif [[ ${ipv6} -eq 1 ]]
105then
106	L4FWD_PORT_PRM="port=${DPDK_PORT},lcore=${L4FWD_BECORE},rx_offload=0x0\
107,tx_offload=0x0,ipv6=${LOCAL_IPV6}"
108fi
109
110# other variables--------------------------------------------------------------
111
112# check if directories on remote are set, if not make one
113ssh ${REMOTE_HOST} mkdir -p {${REMOTE_OUTDIR},${REMOTE_RESDIR}}
114
115# <tc qdisc ... netem ...> instruction to set
116netem="ssh ${REMOTE_HOST} tc qdisc add dev ${REMOTE_IFACE} \
117root netem limit 100000"
118
119# setting for scp which suppresses output of scp when not in verbose mode
120if [[ ${verbose} -eq 1 ]]
121then
122	scp_suppress=""
123else
124	scp_suppress="-q"
125fi
126
127# setting for dd which suppresses output of dd when not in verbose mode
128if [[ ${verbose} -eq 1 ]]
129then
130	dd_suppress=""
131else
132	dd_suppress="status=none"
133fi
134
135# set address to use by netcat
136if [[ ${ipv4} -eq 1 ]]
137then
138	nc_addr=${LOCAL_IPV4}
139elif [[ ${ipv6} -eq 1 ]]
140then
141	nc_addr=${LOCAL_IPV6}
142fi
143
144let "ipv4_elem=(${MASK_IPV4}/8)"
145let "ipv6_elem=(${MASK_IPV6}/16)"
146let "ipv4_elem_rev=4-${ipv4_elem}"
147
148ipv4_append=""
149while [[ ${ipv4_elem_rev} -ne 0 ]]; do
150	ipv4_append="${ipv4_append}.0"
151	let "ipv4_elem_rev=${ipv4_elem_rev}-1"
152done
153
154ipv4_network=$(echo ${REMOTE_IPV4} | cut -d. -f-${ipv4_elem} | \
155	sed 's#.*#&'"${ipv4_append}"'#')
156ipv6_network=$(echo ${REMOTE_IPV6} | cut -d: -f-${ipv6_elem} | sed 's#.*#&::#')
157
158# helper functions-------------------------------------------------------------
159
160# function to check if verbose is set and run command if yes
161if_verbose()
162{
163	if [[ ${verbose} -eq 1 ]]
164	then
165		$@
166	fi
167}
168
169# update results file
170update_results()
171{
172	file=$1
173	status=$2
174	it=$3
175
176	# get only 'real' time in results file
177	$(ssh ${REMOTE_HOST} "awk '/real/{print \$2}' \
178		${REMOTE_RESDIR}/${file}.result.${it} \
179		>> ${REMOTE_RESDIR}/results.out")
180
181	# add file and status of test to results
182	if [[ ${status} -ne 0 ]]
183	then
184		$(ssh ${REMOTE_HOST} "sed -i '$ s_.*_[FAIL]\t&_' \
185			${REMOTE_RESDIR}/results.out")
186	else
187		$(ssh ${REMOTE_HOST} "sed -i '$ s_.*_[OK]\t&_' \
188			${REMOTE_RESDIR}/results.out")
189	fi
190
191	length=$(expr length "${file}")
192	if [[ ${length} -lt 16 ]]
193	then
194		tab="\t\t"
195	else
196		tab="\t"
197	fi
198
199	$(ssh ${REMOTE_HOST} "sed -i '$ s_.*_${file}${tab}&_' \
200		${REMOTE_RESDIR}/results.out")
201}
202
203# start l4fwd app
204l4fwd_start()
205{
206	# create temporary file for command running l4fwd
207	L4FWD_EXEC_FILE=$(mktemp)
208
209	# store run command
210	cat << EOF > ${L4FWD_EXEC_FILE}
211stdbuf -o0 ${L4FWD_PATH} ${L4FWD_CMD_EAL_PRM} -- ${L4FWD_CMD_PRM} \
212${L4FWD_CONFIG} ${L4FWD_PORT_PRM} > ${L4FWD_OUT_FILE} 2>&1 &
213echo \$!
214EOF
215
216	# visual break
217	if_verbose echo -e "\nApp l4fwd started with command:"
218	if_verbose cat ${L4FWD_EXEC_FILE}
219	if_verbose echo ""
220
221	# run l4fwd app and get process ID of it
222	L4FWD_PID=$(/bin/bash ${L4FWD_EXEC_FILE})
223
224	# wait 2s and check if l4fwd is still running (parsing and init OK)
225	sleep 2
226	if [[ ${L4FWD_PID} -ne $(pgrep -o l4fwd) ]]
227	then
228		echo "ERROR: l4fwd app have crashed during initialization"
229		rm -f ${L4FWD_EXEC_FILE}
230		exit 127
231	fi
232}
233
234# stop l4fwd app
235l4fwd_stop()
236{
237	# kill runnning l4fwd app
238	kill -s SIGINT ${L4FWD_PID}
239
240	# remove temporary files
241	rm -f ${L4FWD_EXEC_FILE}
242	rm -f ${L4FWD_FE_CFG_FILE}
243	rm -f ${L4FWD_BE_CFG_FILE}
244}
245
246# helper function to set netem on remote
247setup_netem()
248{
249	# remove netem settings from remote interface if any
250	check_netem=$(ssh ${REMOTE_HOST} "tc qdisc show dev \
251		${REMOTE_IFACE} | grep netem")
252	if [[ -n ${check_netem} ]]
253	then
254		ssh ${REMOTE_HOST} tc qdisc del dev ${REMOTE_IFACE} root
255	fi
256
257	# set default delay for reorder
258	if [[ ${reorder} -ne 0 && ${delay} -eq 0 ]]
259	then
260		delay=20
261	fi
262
263	# set appropriate delay/loss/reorder if specified
264	if [[ ${delay} -ne 0 ]]
265	then
266		netem="${netem} delay ${delay}ms"
267	fi
268
269	if [[ ${loss} -ne 0 ]]
270	then
271		# calculate parameters for Simplified Gilbert model
272		loss_to_set=$(( $(( ${loss} * ${loss_burst} )) \
273/ $(( 100 - ${loss} )) ))
274
275		if [[ ${loss_to_set} -gt 100 ]]
276		then
277			loss_to_set=100
278		fi
279		netem="${netem} loss gemodel ${loss_to_set}% ${loss_burst}%"
280	fi
281
282	if [[ ${reorder} -ne 0 ]]
283	then
284		netem="${netem} reorder 100% gap ${reorder}"
285	fi
286
287	# set netem on remote
288	${netem}
289
290	# visual break of the output
291	if_verbose echo -e "\nNetwork rules on remote set to:"
292
293	# print current netem settings
294	if_verbose ssh ${REMOTE_HOST} tc qdisc show dev ${REMOTE_IFACE}
295}
296
297# configure IPv4 remote machine
298configure_ip4_remote()
299{
300	# visual break of the output
301	if_verbose echo "Setting interface on remote"
302
303	# set remote interface with correct IP address
304	ssh ${REMOTE_HOST} ip link set ${REMOTE_IFACE} down
305	ssh ${REMOTE_HOST} ip addr flush dev ${REMOTE_IFACE}
306	ssh ${REMOTE_HOST} ip addr add ${REMOTE_IPV4}/${MASK_IPV4} \
307		dev ${REMOTE_IFACE}
308	ssh ${REMOTE_HOST} ip link set ${REMOTE_IFACE} up
309	if_verbose ssh ${REMOTE_HOST} ip addr show dev ${REMOTE_IFACE}
310
311	ssh ${REMOTE_HOST} ip neigh flush dev ${REMOTE_IFACE}
312	ssh ${REMOTE_HOST} iptables --flush
313
314	ssh ${REMOTE_HOST} ip route change ${ipv4_network}/${MASK_IPV4} dev \
315		${REMOTE_IFACE} rto_min 30ms
316
317	# construct <tc qdisc ... nete ...> instruction
318	if [[ set_netem -eq 1 ]]
319	then
320		setup_netem
321	fi
322
323	# give linux 1 sec to handle all network settings
324	sleep 1
325}
326
327# configure IPv6 remote machine
328configure_ip6_remote()
329{
330	# visual break of the output
331	if_verbose echo "Setting interface on remote"
332
333	# set remote interface with correct IP address
334	ssh ${REMOTE_HOST} ip link set ${REMOTE_IFACE} down
335	ssh ${REMOTE_HOST} sysctl -q -w \
336		net.ipv6.conf.${REMOTE_IFACE}.disable_ipv6=0
337	ssh ${REMOTE_HOST} ip addr flush dev ${REMOTE_IFACE}
338	ssh ${REMOTE_HOST} ip -6 addr add ${REMOTE_IPV6}/${MASK_IPV6} \
339		dev ${REMOTE_IFACE}
340	ssh ${REMOTE_HOST} ip -6 link set ${REMOTE_IFACE} up
341	if_verbose ssh ${REMOTE_HOST} ip addr show dev ${REMOTE_IFACE}
342
343	ssh ${REMOTE_HOST} ip neigh flush dev ${REMOTE_IFACE}
344	ssh ${REMOTE_HOST} ip -6 neigh add ${LOCAL_IPV6} dev ${REMOTE_IFACE} \
345		lladdr ${LOCAL_MAC}
346	ssh ${REMOTE_HOST} iptables --flush
347	ssh ${REMOTE_HOST} ip6tables --flush
348
349	ssh ${REMOTE_HOST} ip route change ${ipv6_network}/${MASK_IPV6} dev \
350		${REMOTE_IFACE} proto kernel metric 256 rto_min 30ms
351
352	ssh ${REMOTE_HOST} ip -6 route show
353
354	# construct <tc qdisc ... nete ...> instruction
355	if [[ set_netem -eq 1 ]]
356	then
357		setup_netem
358	fi
359
360	# give linux 1 sec to handle all network settings
361	sleep 1
362}
363
364# configure remote
365configure_remote()
366{
367	# call proper configuration
368	if [[ ${ipv4} -eq 1 ]]
369	then
370		configure_ip4_remote
371
372		if_verbose echo -e "\nBE configuration:"
373		config4_be
374
375		if_verbose echo -e "\nFE configuration:"
376		config4_fe
377	elif [[ ${ipv6} -eq 1 ]]
378	then
379		configure_ip6_remote
380
381		if_verbose echo -e "\nBE configuration:"
382		config6_be
383
384		if_verbose echo -e "\nFE configuration:"
385		config6_fe
386	fi
387
388	# create empty results file on remote
389	$(ssh ${REMOTE_HOST} "> ${REMOTE_RESDIR}/results.out")
390}
391
392# restore netem settings to default
393restore_netem()
394{
395	if [[ ${set_netem} -eq 1 ]]
396	then
397		ssh ${REMOTE_HOST} tc qdisc del dev ${REMOTE_IFACE} root
398	fi
399}
400
401# remove created directories after test is done
402remove_directories()
403{
404	ssh ${REMOTE_HOST} rm -fr ${REMOTE_DIR}
405}
406
407# configuration of be/fe config------------------------------------------------
408config4_be()
409{
410	cat <<EOF > ${L4FWD_BE_CFG_FILE}
411port=${DPDK_PORT},masklen=${MASK_IPV4},addr=${REMOTE_IPV4},mac=${REMOTE_MAC}
412EOF
413
414	if_verbose cat ${L4FWD_BE_CFG_FILE}
415}
416
417config6_be()
418{
419	cat <<EOF > ${L4FWD_BE_CFG_FILE}
420port=${DPDK_PORT},masklen=${MASK_IPV6},addr=${REMOTE_IPV6},mac=${REMOTE_MAC}
421EOF
422
423	if_verbose cat ${L4FWD_BE_CFG_FILE}
424}
425
426config4_fe()
427{
428	cat <<EOF > ${L4FWD_FE_CFG_FILE}
429lcore=${L4FWD_FECORE},belcore=${L4FWD_BECORE},op=echo,laddr=${LOCAL_IPV4}\
430,lport=${TCP_PORT},raddr=${REMOTE_IPV4},rport=0
431EOF
432
433	if_verbose cat ${L4FWD_FE_CFG_FILE}
434}
435
436config6_fe()
437{
438	cat <<EOF > ${L4FWD_FE_CFG_FILE}
439lcore=${L4FWD_FECORE},belcore=${L4FWD_BECORE},op=echo,laddr=${LOCAL_IPV6}\
440,lport=${TCP_PORT},raddr=${REMOTE_IPV6},rport=0
441EOF
442
443	if_verbose cat ${L4FWD_FE_CFG_FILE}
444}
445