- add netmap (FreeBSD header files need to be updated with this) - move prototype perl scripts to prototype/ folder - create basic structure for sipcap app (no code yet)
		
			
				
	
	
		
			429 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			429 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| ## Manage linux driver patches for netmap.
 | |
| ## usage (from the dir containing the Makefile):
 | |
| ## 
 | |
| ##    scripts/np <action> [args...]
 | |
| ##
 | |
| ## where <action> is any of the functions below.
 | |
| ##
 | |
| 
 | |
| [ -f scripts/conf ] && source scripts/conf
 | |
| 
 | |
| ## The following enviroment variables must be set:
 | |
| ##
 | |
| ##  GITDIR: the absolute path of the netmap linux
 | |
| ## 	git repository, containing all the required netmap-*
 | |
| ## 	branches.
 | |
| [ -n "$GITDIR" -a -d "$GITDIR/.git" ] || {
 | |
| 	echo "GITDIR not set or not valid" >&2
 | |
| 	exit 1
 | |
| }
 | |
| 
 | |
| NETMAP_BRANCH=${NETMAP_BRANCH:-master}
 | |
| 
 | |
| function error {
 | |
| 	echo "$@" >&2
 | |
| 	exit 1
 | |
| }
 | |
| 
 | |
| function get-params {
 | |
| 	local params=$1; shift
 | |
| 	err_msg="$PROGNAME $COMMAND $(echo $params| perl -pe 's/\S+/<$&>/g')"
 | |
| 	local param
 | |
| 	for param in $params; do
 | |
| 		[[ -z "$@" ]] && error "$err_msg"
 | |
| 		pname=$(echo -n $param | perl -pe 's/\W/_/g')
 | |
| 		eval $pname="$1"
 | |
| 		shift
 | |
| 	done
 | |
| 	[[ -n "$@" ]] && error "$err_msg"
 | |
| }
 | |
| 
 | |
| ##
 | |
| ##  LINUX_SOURCES: the absolute path of a
 | |
| ## 	directory used to store all required linux-* source trees
 | |
| ## 	(The script will extract linux-x.y.z from GITDIR if it needs
 | |
| ## 	it and $LINUX_SOURCES does not already contain it).
 | |
| ##
 | |
| ##  LINUX_CONFIGS: the absolute path of a
 | |
| ## 	directory containing the configuration files for 
 | |
| ## 	the linux kernel. The file for version x must be named
 | |
| ## 	config-x. config-all can be used as a default.
 | |
| ##
 | |
| ## The configuration variables can be put in scripts/conf.
 | |
| ##
 | |
| 
 | |
| ##
 | |
| ## Available actions:
 | |
| ##
 | |
| 
 | |
| ##
 | |
| ##  driver-path <driver> <version>
 | |
| ##	retrieves the path of <driver> in the linux sources
 | |
| ##	for version <version>. The path is output to stdout.
 | |
| ##	It uses a local cache to minimize the expensive
 | |
| ##	file system search.
 | |
| function driver-path()
 | |
| {
 | |
| 	get-params "driver version" "$@"
 | |
| 	
 | |
| 	cat cache/$version/$driver/path 2>/dev/null && return
 | |
| 	local kern=$(get-kernel $version)
 | |
| 	mkdir -p cache/$version/$driver
 | |
| 	(
 | |
| 		cd $kern
 | |
| 		find drivers/net -name $driver
 | |
| 	) | tee cache/$version/$driver/path
 | |
| }
 | |
| 
 | |
| 
 | |
| ##
 | |
| ##  get-patch [-c] <driver> <version>
 | |
| ##	extract the netmap patch for the given <driver> and the
 | |
| ##	given kernel <version>. The patch is stored in tmp-patches
 | |
| ##	and the name of the patch is output to stdout.
 | |
| ##	If a patch with the same name already exists in tmp-patches
 | |
| ##	it is overwritten, unless the -c option is used,
 | |
| ##	in which case the existing patch is kept (the patch name is still output).
 | |
| function get-patch()
 | |
| {
 | |
| 	local use_cache
 | |
| 	[ "$1" = -c ] && { use_cache=1; shift; }
 | |
| 
 | |
| 	get-params "driver version" "$@"
 | |
| 
 | |
| 	# convert kernel version to fixed notation
 | |
| 	local v1=$(scripts/vers $version -c)
 | |
| 	# compute next kernel version (in fixed notation)
 | |
| 	local v2=$(scripts/vers $version -i -c)
 | |
| 	local patchname=diff--$driver--$v1--$v2
 | |
| 	local out=tmp-patches/$patchname
 | |
| 	[ -n "$use_cache" -a -s $out ] && { echo $out; return; }
 | |
| 	local drvpath=$(driver-path $driver $version)
 | |
| 	[ -n "$drvpath" ] || return
 | |
| 	local drvdir=$(dirname $drvpath)
 | |
| 	(
 | |
| 		cd $GITDIR
 | |
| 		git diff --relative=$drvdir v$version..netmap-$version -- $drvpath
 | |
| 	) > $out
 | |
| 	# an empty patch means no netmap support for this driver
 | |
| 	[ -s $out ] || { rm $out; return 1; }
 | |
| 	echo $out
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| ##
 | |
| ##  get-range <driver> <version1> <version2>
 | |
| ##	extracts the netmap patches for the given <driver> for
 | |
| ##	all the kernel versions from <version1> (included) to
 | |
| ##	<version2> (excluded). All patches are stored in tmp-patches
 | |
| ##	and their names are output to stdout.
 | |
| function get-range()
 | |
| {
 | |
| 	get-params "driver version1 version2"	 "$@"
 | |
| 
 | |
| 	local v=$version1
 | |
| 	# while version is less than $version2
 | |
| 	while scripts/vers -b $v $version2 -L; do
 | |
| 		get-patch $driver $v
 | |
| 		# compute next version
 | |
| 		v=$(scripts/vers $v -i)
 | |
| 	done
 | |
| }
 | |
| 
 | |
| 
 | |
| ##
 | |
| ##  get-src <driver> <version> <dest>
 | |
| ##	copies the original sources of the given <driver>,
 | |
| ##	from the given kernel <version> to the given <dest>
 | |
| ##	directory.
 | |
| ##	It uses a local cache to minimize the expensive
 | |
| ##	checkouts in GITDIR.
 | |
| function get-src()
 | |
| {
 | |
| 	get-params "driver version dest" "$@"
 | |
| 
 | |
| 	local kern=$(get-kernel $version)
 | |
| 	local src=$(driver-path $driver $version)
 | |
| 	cp -r $kern/$src $dest
 | |
| }
 | |
| 
 | |
| 
 | |
| ##
 | |
| ##  extend <patch> <version>
 | |
| ##	checks wether the range of applicability of the 
 | |
| ##	given <patch> can be extented to include <version>.
 | |
| ##	It returns 0 on success and 1 on failure.
 | |
| function extend()
 | |
| {
 | |
| 	get-params "patch version" "$@"
 | |
| 
 | |
| 	local _patch=$(realpath $patch)
 | |
| 	# extract the driver name from the patch name
 | |
| 	local driver=$(scripts/vers $_patch -s -p -p)
 | |
| 	local tmpdir1=$(mktemp -d)
 | |
| 	local tmpdir2=$(mktemp -d)
 | |
| 	trap "rm -rf $tmpdir1 $tmpdir2" 0
 | |
| 	# we get the driver sources for the given <version> and
 | |
| 	# we apply two patches separately:
 | |
| 	# i) the given <patch>;
 | |
| 	# ii) the proper patch from GITDIR.
 | |
| 	# We declare <patch> to be extendable if
 | |
| 	# - it is still applicable AND
 | |
| 	# - we obtain the same files from i) and ii) (ignoring whitespace)
 | |
| 	get-src $driver $version $tmpdir1
 | |
| 	get-src $driver $version $tmpdir2
 | |
| 	(
 | |
| 		cd $tmpdir1
 | |
| 		patch --no-backup-if-mismatch -p1 < $_patch >/dev/null 2>&1
 | |
| 	) || return 1
 | |
| 	local patch2=$(get-patch -c $driver $version)
 | |
| 	patch2=$(realpath $patch2)
 | |
| 	(
 | |
| 		cd $tmpdir2
 | |
| 		patch -p1 < $patch2 >/dev/null 2>&1
 | |
| 	) # this will certainly apply
 | |
| 	diff -qbBr $tmpdir1 $tmpdir2 >/dev/null || return 1
 | |
| 	return 0
 | |
| } 
 | |
| 
 | |
| ##
 | |
| ##  minimize <driver>
 | |
| ##	tries to minimize the number of patch files for the given
 | |
| ##	<driver>. It uses the patches currently found in tmp-patches
 | |
| ##	and stores the resulting patches in final-patches.
 | |
| ##	If final-patches already contained patches for <driver>,
 | |
| ##	they are deleted first.
 | |
| function minimize()
 | |
| {
 | |
| 	get-params "driver" "$@"
 | |
| 
 | |
| 	mkdir -p final-patches
 | |
| 	local drv=$(basename $driver)
 | |
| 	local patches=$(ls tmp-patches/diff--$drv--* 2>/dev/null)
 | |
| 	[ -n "$patches" ] || return 1
 | |
| 	# put the patch names in $1, $2, ...
 | |
| 	set $patches
 | |
| 	rm -f final-patches/diff--$drv--*
 | |
| 	# the original patches (in tmp-patches) are ordered by version number.
 | |
| 	# We consider one patch in turn (the 'pivot') and try
 | |
| 	# to extend its range to cover the range of the next
 | |
| 	# patch. If this succedes, the merged patch is the new
 | |
| 	# pivot, otherwise the current pivot is output and the
 | |
| 	# next patch becomes the new pivot. The process
 | |
| 	# is repeated until there are no more patches to consider.
 | |
| 	local pivot=$1
 | |
| 	[ -n "$pivot" -a -e "$pivot" ] || return 1
 | |
| 	# extract the left end and right end of the pivot's range
 | |
| 	local ple=$(scripts/vers $pivot -s -p -C)
 | |
| 	local pre=$(scripts/vers $pivot -s -C)
 | |
| 	while [ -n "$pivot" ]; do
 | |
| 		shift
 | |
| 		if [ -n "$1" ]; then 
 | |
| 			# extract the left end and right end of the next patch
 | |
| 			local nle=$(scripts/vers $1 -s -p -C)
 | |
| 			local nre=$(scripts/vers $1 -s -C)
 | |
| 			# we admit no gaps in the range
 | |
| 			if [ $pre = $nle ] && extend $pivot $nle; then
 | |
| 				pre=$nre
 | |
| 				continue
 | |
| 			fi
 | |
| 		fi
 | |
| 		# either out of patches or failed merge.
 | |
| 		# Compute the file name of the current pivot and store
 | |
| 		# the patch in its final location
 | |
| 		out=$(scripts/vers diff $drv $ple -c $pre -c -S4)
 | |
| 		cp $pivot final-patches/$out
 | |
| 		# the new pivot becames the next patch (if any)
 | |
| 		pivot=$1
 | |
| 		pre=$nre
 | |
| 		ple=$nle
 | |
| 	done
 | |
| 	return 0
 | |
| }
 | |
| 
 | |
| ##
 | |
| ##  infty <driver> <version>
 | |
| ##	if final-patches contains a patch for <driver> with a range
 | |
| ##	ending in <version>, extend it to infinity.
 | |
| ##	Do nothing otherwise.
 | |
| function infty()
 | |
| {
 | |
| 	get-params "driver version" "$@"
 | |
| 
 | |
| 	local drv=$(basename $driver)
 | |
| 	# convert kernel version to fixed notation
 | |
| 	local v=$(scripts/vers $version -c)
 | |
| 	local last=$(ls final-patches/diff--$drv--*--$v 2>/dev/null|tail -n1)
 | |
| 	[ -n "$last" ] || return 1
 | |
| 	mv -n $last $(scripts/vers $last -s -p 99999 -S4) 2>/dev/null
 | |
| }
 | |
| 
 | |
| function get-kernel()
 | |
| {
 | |
| 	get-params "version" "$@"
 | |
| 
 | |
| 	local dst="$(realpath $LINUX_SOURCES)/linux-$version"
 | |
| 
 | |
| 	[ -d $dst ] && { echo $dst; return; }
 | |
| 
 | |
| 	mkdir -p $dst
 | |
| 
 | |
| 	(
 | |
| 		cd $GITDIR
 | |
| 		git archive v$v | tar xf - -C $dst 
 | |
| 	)
 | |
| 	echo $dst
 | |
| }
 | |
| 
 | |
| 
 | |
| ##
 | |
| ##  build-prep <version>
 | |
| ##	prepare the linux tree for <version> to be ready
 | |
| ##	for external modules compilation.
 | |
| ##	The tree is put in $LINUX_SOURCES/linux-<version> and the
 | |
| ##	configuration is obtained from $LINUX_CONFIGS/config-<version>
 | |
| ##	(or $LINUX_CONFIGS/config-all by default).
 | |
| ##	Errors are logged to $LINUX_CONFIGS/linux-<version>.log.
 | |
| ##	If $LINUX_SOURCES/linux-<version> already exists,
 | |
| ##	nothing is done.
 | |
| ##	In all cases, the absolute path of linux-<version> is
 | |
| ##	output.
 | |
| function build-prep()
 | |
| {
 | |
| 	get-params "version" "$@"
 | |
| 
 | |
| 	local dst=$(get-kernel $version)
 | |
| 
 | |
| 	exec 3>&1 4>&2 >$dst.log 2>&1
 | |
| 	cp $LINUX_CONFIGS/config-$v $dst/.config  2>/dev/null ||
 | |
| 	cp $LINUX_CONFIGS/config-all $dst/.config 
 | |
| 	(
 | |
| 		cd $dst
 | |
| 		yes '' | make oldconfig
 | |
| 		make modules_prepare
 | |
| 	)
 | |
| 	exec 1>&3 2>&4
 | |
| 	echo $dst
 | |
| }
 | |
| 
 | |
| ##
 | |
| ##  check-patch <patch>
 | |
| ##	check that the given <patch> applies and compiles without
 | |
| ##	error for all its declared range of applicability.
 | |
| ##	Errors are logged to log/<patch>.
 | |
| function check-patch()
 | |
| {
 | |
| 	get-params "patch" "$@"
 | |
| 
 | |
| 	# extract the left version
 | |
| 	local v1=$(scripts/vers $patch -s -p -C)
 | |
| 	# extract the right version
 | |
| 	local v2=$(scripts/vers $patch -s -C)
 | |
| 	# extract the driver name
 | |
| 	local driver=$(scripts/vers $patch -s -p -p)
 | |
| 	local p=$(realpath $patch)
 | |
| 	mkdir -p log
 | |
| 	local log="$(realpath log)/$(basename $patch)"
 | |
| 	local nmcommit=$(cd ..; git show-ref -s heads/$NETMAP_BRANCH)
 | |
| 
 | |
| 	echo -n $patch...
 | |
| 
 | |
| 	while scripts/vers -b $v1 $v2 -L; do
 | |
| 		# cache lookup
 | |
| 		local cache=cache/$v1/$driver
 | |
| 		local cpatch=$cache/patch
 | |
| 		local cnmcommit=$cache/nmcommit
 | |
| 		local cstatus=$cache/status
 | |
| 		local clog=$cache/log
 | |
| 		if [ -f $cpatch ]				&&
 | |
| 		   cmp -s $cpatch $patch			&&
 | |
| 		   [ "$nmcommit" = "$(cat $cnmcommit)" ]; then
 | |
| 			cp $clog $log
 | |
| 			ok=$(cat $cstatus)
 | |
| 		else
 | |
| 			# update cache
 | |
| 			cp $patch $cpatch
 | |
| 			echo $nmcommit > $cnmcommit
 | |
| 
 | |
| 			local ksrc=$(build-prep $v1)
 | |
| 			local tmpdir=$(mktemp -d)
 | |
| 			trap "rm -rf $tmpdir" 0
 | |
| 			(cd ..; git archive $NETMAP_BRANCH | tar xf - -C $tmpdir )
 | |
| 			pushd $tmpdir/LINUX >/dev/null
 | |
| 			mkdir single-patch
 | |
| 			rm patches
 | |
| 			ln -s single-patch patches
 | |
| 			cp $p single-patch
 | |
| 			ok=false
 | |
| 			make KSRC=$ksrc >$log 2>&1 && ok=true
 | |
| 			popd >/dev/null
 | |
| 			cp $log $clog
 | |
| 		fi
 | |
| 		[ $ok = true ] || { echo FAILED; echo false > $cstatus; return 1; }
 | |
| 		echo true > $cstatus
 | |
| 		rm -rf $tmpdir
 | |
| 		# compute next version
 | |
| 		v1=$(scripts/vers $v1 -i)
 | |
| 	done
 | |
| 	echo OK
 | |
| }
 | |
| 
 | |
| ##
 | |
| ##  build-check <driver>
 | |
| ##	do a check-patch for all the patches of <driver> that are
 | |
| ##	currently in tmp-patches. Patches that fail the check
 | |
| ##	are moved to failed-patches.
 | |
| function build-check()
 | |
| {
 | |
| 	get-params "driver" "$@"
 | |
| 
 | |
| 	mkdir -p failed-patches
 | |
| 	local drv=$(basename $driver)
 | |
| 	local patches=$(ls tmp-patches/diff--$drv--* 2>/dev/null)
 | |
| 	local p
 | |
| 	for p in $patches; do
 | |
| 		check-patch $p || mv $p failed-patches
 | |
| 	done
 | |
| }
 | |
| 
 | |
| ##
 | |
| ##  forall <cmd> [args...]
 | |
| ##	exec <cmd> <driver> [args...] for all known drivers.
 | |
| function forall()
 | |
| {
 | |
| 	local cmd=$1
 | |
| 	shift
 | |
| 	# we obtain the value of DRIVER_SRC from the makefile
 | |
| 	# (the +% target is defined in our Makefile and prints
 | |
| 	# the contents of variable %)
 | |
| 	local driver_srcs=$(make +DRIVER_SRCS)
 | |
| 
 | |
| 	local driver
 | |
| 	for driver in $driver_srcs; do
 | |
| 		$cmd $(basename $driver) "$@"
 | |
| 	done
 | |
| }
 | |
| 
 | |
| mkdir -p tmp-patches
 | |
| 
 | |
| PROGNAME=$0
 | |
| 
 | |
| [ -n "$1" ] || {
 | |
| 	scripts/help $PROGNAME;
 | |
| 	exit 1
 | |
| }
 | |
| 
 | |
| COMMAND=$1; shift
 | |
| case $COMMAND in
 | |
| *-all)
 | |
| 	forall ${COMMAND%-all} "$@"
 | |
| 	;;
 | |
| -[hH]|--help|-help|help)
 | |
| 	scripts/help $PROGNAME
 | |
| 	;;
 | |
| *)
 | |
| 	$COMMAND "$@"
 | |
| 	;;
 | |
| esac
 |