ia64/xen-unstable
changeset 3094:42bdac6c8985
bitkeeper revision 1.1159.1.445 (41a47974rZ1vtGT5wjpKwbMSnQ8gwA)
sync w/ head.
sync w/ head.
line diff
1.1 --- a/.rootkeys Wed Nov 24 11:51:49 2004 +0000 1.2 +++ b/.rootkeys Wed Nov 24 12:07:16 2004 +0000 1.3 @@ -127,6 +127,7 @@ 409ba2e7akOFqQUg6Qyg2s28xcXiMg linux-2.4 1.4 3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.27-xen-sparse/mm/swapfile.c 1.5 41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.27-xen-sparse/mm/vmalloc.c 1.6 41505c57WAd5l1rlfCLNSCpx9J13vA linux-2.4.27-xen-sparse/net/core/skbuff.c 1.7 +41a270bfmh73b5G5UMWfoUZhxoIjTg linux-2.6.9-xen-sparse/Makefile 1.8 40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.9-xen-sparse/arch/xen/Kconfig 1.9 40f56237utH41NPukqHksuNf29IC9A linux-2.6.9-xen-sparse/arch/xen/Kconfig.drivers 1.10 40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.9-xen-sparse/arch/xen/Makefile 1.11 @@ -195,6 +196,12 @@ 40f562395atl9x4suKGhPkjqLOXESg linux-2.6 1.12 40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c 1.13 40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.9-xen-sparse/drivers/xen/blkfront/block.h 1.14 40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.9-xen-sparse/drivers/xen/blkfront/vbd.c 1.15 +41a226e0vjAcDXHOnXE5ummcdUD2mg linux-2.6.9-xen-sparse/drivers/xen/blktap/Makefile 1.16 +41a226e0VeZA1N8tbU6nvJ3OxUcJmw linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.c 1.17 +41a226e1k4J5VMLnrYXDWRqElS49YQ linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.h 1.18 +41a226e1-A_Hy7utS8vJKaXnH_tzfA linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c 1.19 +41a226e19NoUUTOvs7jumDMRYDIO4Q linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_datapath.c 1.20 +41a226e1MNSyWWK5dEVgvSQ5OW0fDA linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_userdev.c 1.21 40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.9-xen-sparse/drivers/xen/console/Makefile 1.22 3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.9-xen-sparse/drivers/xen/console/console.c 1.23 40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.9-xen-sparse/drivers/xen/evtchn/Makefile 1.24 @@ -341,20 +348,35 @@ 40589968UQFnJeOMn8UIFLbXBuwXjw tools/lib 1.25 40e1b09dMYB4ItGCqcMIzirdMd9I-w tools/libxutil/Makefile 1.26 40e033325Sjqs-_4TuzeUEprP_gYFg tools/libxutil/allocate.c 1.27 40e03332KYz7o1bn2MG_KPbBlyoIMA tools/libxutil/allocate.h 1.28 +41a216cav5JJbtDQnusfuMa_1x_Xpw tools/libxutil/debug.h 1.29 +40e9808eyjiahG5uF6AMelNVujBzCg tools/libxutil/enum.c 1.30 +40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/libxutil/enum.h 1.31 40e03332p5Dc_owJQRuN72ymJZddFQ tools/libxutil/file_stream.c 1.32 40e03332jWfB2viAhLSkq1WK0r_iDQ tools/libxutil/file_stream.h 1.33 40e03332rUjNMGg11n2rN6V4DCrvOg tools/libxutil/gzip_stream.c 1.34 40e033321O5Qg22haLoq5lpmk4tooQ tools/libxutil/gzip_stream.h 1.35 +40e9808easXCzzAZQodEfKAhgUXSPA tools/libxutil/hash_table.c 1.36 +40e9808e94BNXIVVKBFHC3rnkvwtJg tools/libxutil/hash_table.h 1.37 40e03332ihnBGzHykVwZnFmkAppb4g tools/libxutil/iostream.c 1.38 40e03332UGwbLR4wsw4ft14p0Yw5pg tools/libxutil/iostream.h 1.39 40e0333245DLDzJemeSVBLuutHtzEQ tools/libxutil/kernel_stream.c 1.40 40e03332aK0GkgpDdc-PVTkWKTeOBg tools/libxutil/kernel_stream.h 1.41 +40e9808epW9iHcLXuO3QfUfLzB7onw tools/libxutil/lexis.c 1.42 +40e9808egccMhCizayQRGtpBA3L5MQ tools/libxutil/lexis.h 1.43 +41a216caM4z39Fzjb91rv9Ed_4By1A tools/libxutil/socket_stream.c 1.44 +41a216caqinvF1I5FQMHA4HTRz8MSA tools/libxutil/socket_stream.h 1.45 40e03332KT_tnnoAMbPVAZBB7kSOAQ tools/libxutil/string_stream.c 1.46 40e03332-VtK6_OZa1vMHXFil8uq6w tools/libxutil/string_stream.h 1.47 +40e9808e5_PLdodqVOSx0b4T_f5aeg tools/libxutil/sxpr.c 1.48 +40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/libxutil/sxpr.h 1.49 +40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/libxutil/sxpr_parser.c 1.50 +40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/libxutil/sxpr_parser.h 1.51 40e03332Rkvq6nn_UNjzAAK_Tk9v1g tools/libxutil/sys_net.c 1.52 40e03332lQHvQHw4Rh7VsT1_sui29A tools/libxutil/sys_net.h 1.53 40e033321smklZd7bDSdWvQCeIshtg tools/libxutil/sys_string.c 1.54 40e03332h5V611rRWURRLqb1Ekatxg tools/libxutil/sys_string.h 1.55 +41a216cayFe2FQroFuzvNPw1AvNiqQ tools/libxutil/util.c 1.56 +41a216ca7mgVSnCBHPCLkGOIqPS1CQ tools/libxutil/util.h 1.57 3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile 1.58 40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen 1.59 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile 1.60 @@ -533,6 +555,64 @@ 4104ffca-jPHLVOrW0n0VghEXXtKxg tools/sv/ 1.61 40fcefb3yMSrZvApO9ToIi-iQwnchA tools/sv/images/xen.png 1.62 41013a83z27rKvWIxAfUBMVZ1eDCDg tools/sv/inc/script.js 1.63 40fcefb3zGC9XNBkSwTEobCoq8YClA tools/sv/inc/style.css 1.64 +41a21888_WlknVWjSxb32Fo13_ujsw tools/vnet/00README 1.65 +41a21888bOiOJc7blzRbe4MNJoaYTw tools/vnet/Makefile 1.66 +41a21888mg2k5HeiVjlQYEtJBZT4Qg tools/vnet/doc/vnet-module.txt 1.67 +41a21888cuxfT8wjCdRR6V1lqf5NtA tools/vnet/doc/vnet-xend.txt 1.68 +41a21888xEQJAIGktS6XQ4xz2TyA5g tools/vnet/examples/Makefile 1.69 +41a21888FGQhPR5LJ1GRtOSIIN3QEw tools/vnet/examples/network-vnet 1.70 +41a21888QPgKrulCfR9SY_pxZKU0KA tools/vnet/examples/vnet97.sxp 1.71 +41a21888Gm0UBs1i7HqveT7Yz0u8DQ tools/vnet/examples/vnet98.sxp 1.72 +41a21888r4oGPuGv2Lxl-thgV3H54w tools/vnet/examples/vnet99.sxp 1.73 +41a21888c9TCRlUwJS9WBjB3e9aWgg tools/vnet/vnet-module/00README 1.74 +41a21888K2ItolEkksc1MUqyTDI_Kg tools/vnet/vnet-module/Makefile 1.75 +41a21888mJsFJD7bVMm-nrnWnalGBw tools/vnet/vnet-module/Makefile-2.4 1.76 +41a21888Znze3-UCCBZ-Nxpj-bNeHA tools/vnet/vnet-module/Makefile-2.6 1.77 +41a21889fwc1judJ7DYvyEviSJ3TPg tools/vnet/vnet-module/Makefile.ver 1.78 +41a21889m_sYkdODF3j5uhMP-Guy9Q tools/vnet/vnet-module/Makefile.vnet 1.79 +41a21889bXW2lC28U6KS_s5tOJ_W9Q tools/vnet/vnet-module/esp.c 1.80 +41a21889L2MfLDsUFQxstt-0frIVmw tools/vnet/vnet-module/esp.h 1.81 +41a21889V1jOsB2JExI-XQl720WHwg tools/vnet/vnet-module/etherip.c 1.82 +41a21889IpMYbNufHMDXe2ndNw4JxA tools/vnet/vnet-module/etherip.h 1.83 +41a21889LT9TNqO2EvTFIUTujrkX9w tools/vnet/vnet-module/if_etherip.h 1.84 +41a21889PESythGZFG6kmSoOkkN2Nw tools/vnet/vnet-module/if_varp.h 1.85 +41a21889nCPEomHqOyQ4vnhEm4II4g tools/vnet/vnet-module/linux/pfkeyv2.h 1.86 +41a21889A_fw4pRmCbBfZdtRunM5Eg tools/vnet/vnet-module/random.c 1.87 +41a218899Xy2dPKSu3pkuqaqkfKMTA tools/vnet/vnet-module/random.h 1.88 +41a21889rIH5S1dv8ygdSsTGNlg0JA tools/vnet/vnet-module/sa.c 1.89 +41a218896Z4vxy6gnV9h0fWRWu0lKQ tools/vnet/vnet-module/sa.h 1.90 +41a21889qFD8BTbDpB55uVmSVDEsgw tools/vnet/vnet-module/sa_algorithm.c 1.91 +41a21889r2AwTe-OCSSVMxBzz8uDtw tools/vnet/vnet-module/sa_algorithm.h 1.92 +41a21889tvjtL7O8tMveVB8MdSKPnQ tools/vnet/vnet-module/skb_context.c 1.93 +41a21889lD_QOUz2Msd7fB5rJQzfxA tools/vnet/vnet-module/skb_context.h 1.94 +41a21889F1r1xnJamzdeuClR8MNwQg tools/vnet/vnet-module/skb_util.c 1.95 +41a21889sS4bjVqEna24sS8NpV7SRA tools/vnet/vnet-module/skb_util.h 1.96 +41a21889MDawEK3J_f_oAGnZznhG2w tools/vnet/vnet-module/tunnel.c 1.97 +41a218896TlHXpVVqF50uz_u_WMXRw tools/vnet/vnet-module/tunnel.h 1.98 +41a21889nQYbJbqrOApg_RbkwPtXGg tools/vnet/vnet-module/varp.c 1.99 +41a21889Pev5MJlqqass6CxN4mmvPw tools/vnet/vnet-module/varp.h 1.100 +41a21889GbsHHfkpA-PkOvltfEwpMA tools/vnet/vnet-module/varp_socket.c 1.101 +41a21889sknn8zd5xCJlpQbs7MvxKg tools/vnet/vnet-module/vif.c 1.102 +41a21889VsKKWpe6rcXOSLPy2FuNWQ tools/vnet/vnet-module/vif.h 1.103 +41a21889dgkOyuSTVqy7D8TPIzrUyw tools/vnet/vnet-module/vnet.c 1.104 +41a21889ocAdwk7V1nNt4iBpmYW-Mw tools/vnet/vnet-module/vnet.h 1.105 +41a21889YrTiC0ArJSGFtiaHz2j1qQ tools/vnet/vnet-module/vnet_dev.c 1.106 +41a21889rHT4vrC4VAfk7-xP_K5aBg tools/vnet/vnet-module/vnet_dev.h 1.107 +41a21889qJj6GjT2f5hMHRvPS1AW4w tools/vnet/vnet-module/vnet_ioctl.c 1.108 +41a2188a8W4xYB0LYm512agtoEv52g tools/vnet/vnet-module/vnet_ioctl.h 1.109 +41a2188aFF_1T9OgpqUjjjaCqKB8lw tools/vnet/vnetd/Makefile 1.110 +41a2188a9j84qS4CxqMLVCvyGpA93w tools/vnet/vnetd/connection.c 1.111 +41a2188atexNEami9TNVYNkRSb7Bqg tools/vnet/vnetd/connection.h 1.112 +41a2188abgYpITSrWoMGHHrM56nklw tools/vnet/vnetd/marshal.c 1.113 +41a2188aUbOi5tAYwOS4aPixo1EGwQ tools/vnet/vnetd/marshal.h 1.114 +41a2188aDJlSVB1s_st2MSWxW8kMwg tools/vnet/vnetd/select.c 1.115 +41a2188aE9LUDdSSwNT3BWVWCvGSnQ tools/vnet/vnetd/select.h 1.116 +41a2188aTbMKv_Eig12dSrBUEBl1Jg tools/vnet/vnetd/timer.c 1.117 +41a2188aIzBGqQ6DUVzCxfBsN0Q6Ww tools/vnet/vnetd/timer.h 1.118 +41a2188aIf3Xk6uvk7KzjdpOsflAEw tools/vnet/vnetd/vcache.c 1.119 +41a2188ar6_vOO3_tEJQjmFVU3409A tools/vnet/vnetd/vcache.h 1.120 +41a2188aETrGU60X9WtGhYVfU7z0Pw tools/vnet/vnetd/vnetd.c 1.121 +41a2188ahYjemudGyB7078AWMFR-0w tools/vnet/vnetd/vnetd.h 1.122 4194e861IgTabTt8HOuh143QIJFD1Q tools/x2d2/Makefile 1.123 4194e861M2gcBz4i94cQYpqzi8n6UA tools/x2d2/cntrl_con.c 1.124 4194e8612TrrMvC8ZlA4h2ZYCPWz4g tools/x2d2/minixend.c 1.125 @@ -549,23 +629,13 @@ 40e9808epTR4zWrYjGUnaaynK20Q5A tools/xfr 1.126 40e9808eysqT4VNDlJFqsZB2rdg4Qw tools/xfrd/connection.c 1.127 40e9808eyXfJUi4E0C3WSgrEXqQ1sQ tools/xfrd/connection.h 1.128 40e9808eULGwffNOE4kBrAfZ9YAVMA tools/xfrd/debug.h 1.129 -40e9808eyjiahG5uF6AMelNVujBzCg tools/xfrd/enum.c 1.130 -40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/xfrd/enum.h 1.131 -40e9808easXCzzAZQodEfKAhgUXSPA tools/xfrd/hash_table.c 1.132 -40e9808e94BNXIVVKBFHC3rnkvwtJg tools/xfrd/hash_table.h 1.133 411b5139tfKZfWs1LQHmwDR_wjKoxQ tools/xfrd/http.h 1.134 -40e9808epW9iHcLXuO3QfUfLzB7onw tools/xfrd/lexis.c 1.135 -40e9808egccMhCizayQRGtpBA3L5MQ tools/xfrd/lexis.h 1.136 40e9808ePADCSKL1YgGCt2TbYPnYkw tools/xfrd/lzi_stream.c 1.137 40e9808eDNAdpF71o5teYb9DTT-PRw tools/xfrd/lzi_stream.h 1.138 40e9808eQxi0EzTcPJtosrzxEIjA-Q tools/xfrd/marshal.c 1.139 40e9808etg13xfRm0Lqd8vY-jHOoTg tools/xfrd/marshal.h 1.140 40e9808eCsmywryb036TdtRMJHDMmQ tools/xfrd/select.c 1.141 40e9808e99OcM547cKMTfmCVSoWVAw tools/xfrd/select.h 1.142 -40e9808e5_PLdodqVOSx0b4T_f5aeg tools/xfrd/sxpr.c 1.143 -40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/xfrd/sxpr.h 1.144 -40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/xfrd/sxpr_parser.c 1.145 -40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/xfrd/sxpr_parser.h 1.146 40e9808eF3NVldqRNS5IHM8gbFAvpw tools/xfrd/xdr.c 1.147 40e9808ezXzoRHm7pybXU69NtnjimA tools/xfrd/xdr.h 1.148 40e9808edpUtf4bJ8IbqClPJj_OvbA tools/xfrd/xen_domain.c 1.149 @@ -576,6 +646,11 @@ 40e9808eHXvs_5eggj9McD_J90mhNw tools/xfr 1.150 3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING 1.151 3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile 1.152 3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk 1.153 +41a26ebcqaSGVQ8qTMwpPwOJSJ7qSw xen/arch/ia64/privop.c 1.154 +41a26ebc4BOHDUsT0TSnryPeV2xfRA xen/arch/ia64/process.c 1.155 +41a26ebcJ30TFl1v2kR8rqpEBvOtVw xen/arch/ia64/regionreg.c 1.156 +41a26ebc--sjlYZQxmIxyCx3jw70qA xen/arch/ia64/vcpu.c 1.157 +41a26ebc4jSBGQOuyNIPDST58mNbBw xen/arch/ia64/xenasm.S 1.158 3ddb79bcZbRBzT3elFWSX7u6NtMagQ xen/arch/x86/Makefile 1.159 3ddb79bcBQF85CfLS4i1WGZ4oLLaCA xen/arch/x86/Rules.mk 1.160 3e5636e5FAYZ5_vQnmgwFJfSdmO5Mw xen/arch/x86/acpi.c
2.1 --- a/BitKeeper/etc/ignore Wed Nov 24 11:51:49 2004 +0000 2.2 +++ b/BitKeeper/etc/ignore Wed Nov 24 12:07:16 2004 +0000 2.3 @@ -63,6 +63,13 @@ tools/check/.* 2.4 tools/libxc/xen/* 2.5 tools/misc/miniterm/miniterm 2.6 tools/misc/xen_cpuperf 2.7 +tools/vnet/gc 2.8 +tools/vnet/gc*/* 2.9 +tools/vnet/vnet-module/*.ko 2.10 +tools/vnet/vnet-module/.*.cmd 2.11 +tools/vnet/vnet-module/.tmp_versions/* 2.12 +tools/vnet/vnet-module/vnet_module.mod.* 2.13 +tools/vnetd/vnetd 2.14 tools/web-shutdown.tap 2.15 tools/x2d2/minixend 2.16 tools/xentrace/xentrace
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/linux-2.6.9-xen-sparse/Makefile Wed Nov 24 12:07:16 2004 +0000 3.3 @@ -0,0 +1,1293 @@ 3.4 +VERSION = 2 3.5 +PATCHLEVEL = 6 3.6 +SUBLEVEL = 9 3.7 +EXTRAVERSION = 3.8 +NAME=Zonked Quokka 3.9 + 3.10 +# *DOCUMENTATION* 3.11 +# To see a list of typical targets execute "make help" 3.12 +# More info can be located in ./README 3.13 +# Comments in this file are targeted only to the developer, do not 3.14 +# expect to learn how to build the kernel reading this file. 3.15 + 3.16 +# Do not print "Entering directory ..." 3.17 +MAKEFLAGS += --no-print-directory 3.18 + 3.19 +# We are using a recursive build, so we need to do a little thinking 3.20 +# to get the ordering right. 3.21 +# 3.22 +# Most importantly: sub-Makefiles should only ever modify files in 3.23 +# their own directory. If in some directory we have a dependency on 3.24 +# a file in another dir (which doesn't happen often, but it's of 3.25 +# unavoidable when linking the built-in.o targets which finally 3.26 +# turn into vmlinux), we will call a sub make in that other dir, and 3.27 +# after that we are sure that everything which is in that other dir 3.28 +# is now up to date. 3.29 +# 3.30 +# The only cases where we need to modify files which have global 3.31 +# effects are thus separated out and done before the recursive 3.32 +# descending is started. They are now explicitly listed as the 3.33 +# prepare rule. 3.34 + 3.35 +# To put more focus on warnings, be less verbose as default 3.36 +# Use 'make V=1' to see the full commands 3.37 + 3.38 +ifdef V 3.39 + ifeq ("$(origin V)", "command line") 3.40 + KBUILD_VERBOSE = $(V) 3.41 + endif 3.42 +endif 3.43 +ifndef KBUILD_VERBOSE 3.44 + KBUILD_VERBOSE = 0 3.45 +endif 3.46 + 3.47 +# Call sparse as part of compilation of C files 3.48 +# Use 'make C=1' to enable sparse checking 3.49 + 3.50 +ifdef C 3.51 + ifeq ("$(origin C)", "command line") 3.52 + KBUILD_CHECKSRC = $(C) 3.53 + endif 3.54 +endif 3.55 +ifndef KBUILD_CHECKSRC 3.56 + KBUILD_CHECKSRC = 0 3.57 +endif 3.58 + 3.59 +# Use make M=dir to specify directory of external module to build 3.60 +# Old syntax make ... SUBDIRS=$PWD is still supported 3.61 +# Setting the environment variable KBUILD_EXTMOD take precedence 3.62 +ifdef SUBDIRS 3.63 + KBUILD_EXTMOD ?= $(SUBDIRS) 3.64 +endif 3.65 +ifdef M 3.66 + ifeq ("$(origin M)", "command line") 3.67 + KBUILD_EXTMOD := $(M) 3.68 + endif 3.69 +endif 3.70 + 3.71 + 3.72 +# kbuild supports saving output files in a separate directory. 3.73 +# To locate output files in a separate directory two syntax'es are supported. 3.74 +# In both cases the working directory must be the root of the kernel src. 3.75 +# 1) O= 3.76 +# Use "make O=dir/to/store/output/files/" 3.77 +# 3.78 +# 2) Set KBUILD_OUTPUT 3.79 +# Set the environment variable KBUILD_OUTPUT to point to the directory 3.80 +# where the output files shall be placed. 3.81 +# export KBUILD_OUTPUT=dir/to/store/output/files/ 3.82 +# make 3.83 +# 3.84 +# The O= assigment takes precedence over the KBUILD_OUTPUT environment variable. 3.85 + 3.86 + 3.87 +# KBUILD_SRC is set on invocation of make in OBJ directory 3.88 +# KBUILD_SRC is not intended to be used by the regular user (for now) 3.89 +ifeq ($(KBUILD_SRC),) 3.90 + 3.91 +# OK, Make called in directory where kernel src resides 3.92 +# Do we want to locate output files in a separate directory? 3.93 +ifdef O 3.94 + ifeq ("$(origin O)", "command line") 3.95 + KBUILD_OUTPUT := $(O) 3.96 + endif 3.97 +endif 3.98 + 3.99 +# That's our default target when none is given on the command line 3.100 +.PHONY: _all 3.101 +_all: 3.102 + 3.103 +ifneq ($(KBUILD_OUTPUT),) 3.104 +# Invoke a second make in the output directory, passing relevant variables 3.105 +# check that the output directory actually exists 3.106 +saved-output := $(KBUILD_OUTPUT) 3.107 +KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd) 3.108 +$(if $(KBUILD_OUTPUT),, \ 3.109 + $(error output directory "$(saved-output)" does not exist)) 3.110 + 3.111 +.PHONY: $(MAKECMDGOALS) 3.112 + 3.113 +$(filter-out _all,$(MAKECMDGOALS)) _all: 3.114 + $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \ 3.115 + KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \ 3.116 + KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD="$(KBUILD_EXTMOD)" \ 3.117 + -f $(CURDIR)/Makefile $@ 3.118 + 3.119 +# Leave processing to above invocation of make 3.120 +skip-makefile := 1 3.121 +endif # ifneq ($(KBUILD_OUTPUT),) 3.122 +endif # ifeq ($(KBUILD_SRC),) 3.123 + 3.124 +# We process the rest of the Makefile if this is the final invocation of make 3.125 +ifeq ($(skip-makefile),) 3.126 + 3.127 +# If building an external module we do not care about the all: rule 3.128 +# but instead _all depend on modules 3.129 +.PHONY: all 3.130 +ifeq ($(KBUILD_EXTMOD),) 3.131 +_all: all 3.132 +else 3.133 +_all: modules 3.134 +endif 3.135 + 3.136 +srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR)) 3.137 +TOPDIR := $(srctree) 3.138 +# FIXME - TOPDIR is obsolete, use srctree/objtree 3.139 +objtree := $(CURDIR) 3.140 +src := $(srctree) 3.141 +obj := $(objtree) 3.142 + 3.143 +VPATH := $(srctree) 3.144 + 3.145 +export srctree objtree VPATH TOPDIR 3.146 + 3.147 +nullstring := 3.148 +space := $(nullstring) # end of line 3.149 + 3.150 +# Take the contents of any files called localversion* and the config 3.151 +# variable CONFIG_LOCALVERSION and append them to KERNELRELEASE. Be 3.152 +# careful not to include files twice if building in the source 3.153 +# directory. LOCALVERSION from the command line override all of this 3.154 + 3.155 +ifeq ($(objtree),$(srctree)) 3.156 +localversion-files := $(wildcard $(srctree)/localversion*) 3.157 +else 3.158 +localversion-files := $(wildcard $(objtree)/localversion* $(srctree)/localversion*) 3.159 +endif 3.160 + 3.161 +LOCALVERSION = $(subst $(space),, \ 3.162 + $(shell cat /dev/null $(localversion-files)) \ 3.163 + $(subst ",,$(CONFIG_LOCALVERSION))) 3.164 + 3.165 +KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION) 3.166 + 3.167 +# SUBARCH tells the usermode build what the underlying arch is. That is set 3.168 +# first, and if a usermode build is happening, the "ARCH=um" on the command 3.169 +# line overrides the setting of ARCH below. If a native build is happening, 3.170 +# then ARCH is assigned, getting whatever value it gets normally, and 3.171 +# SUBARCH is subsequently ignored. 3.172 + 3.173 +SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ 3.174 + -e s/arm.*/arm/ -e s/sa110/arm/ \ 3.175 + -e s/s390x/s390/ -e s/parisc64/parisc/ ) 3.176 + 3.177 +# Cross compiling and selecting different set of gcc/bin-utils 3.178 +# --------------------------------------------------------------------------- 3.179 +# 3.180 +# When performing cross compilation for other architectures ARCH shall be set 3.181 +# to the target architecture. (See arch/* for the possibilities). 3.182 +# ARCH can be set during invocation of make: 3.183 +# make ARCH=ia64 3.184 +# Another way is to have ARCH set in the environment. 3.185 +# The default ARCH is the host where make is executed. 3.186 + 3.187 +# CROSS_COMPILE specify the prefix used for all executables used 3.188 +# during compilation. Only gcc and related bin-utils executables 3.189 +# are prefixed with $(CROSS_COMPILE). 3.190 +# CROSS_COMPILE can be set on the command line 3.191 +# make CROSS_COMPILE=ia64-linux- 3.192 +# Alternatively CROSS_COMPILE can be set in the environment. 3.193 +# Default value for CROSS_COMPILE is not to prefix executables 3.194 +# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile 3.195 + 3.196 +ARCH ?= $(SUBARCH) 3.197 +CROSS_COMPILE ?= 3.198 + 3.199 +# Architecture as present in compile.h 3.200 +UTS_MACHINE := $(ARCH) 3.201 + 3.202 +# SHELL used by kbuild 3.203 +CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ 3.204 + else if [ -x /bin/bash ]; then echo /bin/bash; \ 3.205 + else echo sh; fi ; fi) 3.206 + 3.207 +HOSTCC = gcc 3.208 +HOSTCXX = g++ 3.209 +HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer 3.210 +HOSTCXXFLAGS = -O2 3.211 + 3.212 +# Decide whether to build built-in, modular, or both. 3.213 +# Normally, just do built-in. 3.214 + 3.215 +KBUILD_MODULES := 3.216 +KBUILD_BUILTIN := 1 3.217 + 3.218 +# If we have only "make modules", don't compile built-in objects. 3.219 +# When we're building modules with modversions, we need to consider 3.220 +# the built-in objects during the descend as well, in order to 3.221 +# make sure the checksums are uptodate before we record them. 3.222 + 3.223 +ifeq ($(MAKECMDGOALS),modules) 3.224 + KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1) 3.225 +endif 3.226 + 3.227 +# If we have "make <whatever> modules", compile modules 3.228 +# in addition to whatever we do anyway. 3.229 +# Just "make" or "make all" shall build modules as well 3.230 + 3.231 +ifneq ($(filter all _all modules,$(MAKECMDGOALS)),) 3.232 + KBUILD_MODULES := 1 3.233 +endif 3.234 + 3.235 +ifeq ($(MAKECMDGOALS),) 3.236 + KBUILD_MODULES := 1 3.237 +endif 3.238 + 3.239 +export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE 3.240 +export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD 3.241 + 3.242 +# Beautify output 3.243 +# --------------------------------------------------------------------------- 3.244 +# 3.245 +# Normally, we echo the whole command before executing it. By making 3.246 +# that echo $($(quiet)$(cmd)), we now have the possibility to set 3.247 +# $(quiet) to choose other forms of output instead, e.g. 3.248 +# 3.249 +# quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@ 3.250 +# cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< 3.251 +# 3.252 +# If $(quiet) is empty, the whole command will be printed. 3.253 +# If it is set to "quiet_", only the short version will be printed. 3.254 +# If it is set to "silent_", nothing wil be printed at all, since 3.255 +# the variable $(silent_cmd_cc_o_c) doesn't exist. 3.256 +# 3.257 +# A simple variant is to prefix commands with $(Q) - that's usefull 3.258 +# for commands that shall be hidden in non-verbose mode. 3.259 +# 3.260 +# $(Q)ln $@ :< 3.261 +# 3.262 +# If KBUILD_VERBOSE equals 0 then the above command will be hidden. 3.263 +# If KBUILD_VERBOSE equals 1 then the above command is displayed. 3.264 + 3.265 +ifeq ($(KBUILD_VERBOSE),1) 3.266 + quiet = 3.267 + Q = 3.268 +else 3.269 + quiet=quiet_ 3.270 + Q = @ 3.271 +endif 3.272 + 3.273 +# If the user is running make -s (silent mode), suppress echoing of 3.274 +# commands 3.275 + 3.276 +ifneq ($(findstring s,$(MAKEFLAGS)),) 3.277 + quiet=silent_ 3.278 +endif 3.279 + 3.280 +export quiet Q KBUILD_VERBOSE 3.281 + 3.282 +###### 3.283 +# cc support functions to be used (only) in arch/$(ARCH)/Makefile 3.284 +# See documentation in Documentation/kbuild/makefiles.txt 3.285 + 3.286 +# cc-option 3.287 +# Usage: cflags-y += $(call gcc-option, -march=winchip-c6, -march=i586) 3.288 + 3.289 +cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ 3.290 + > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) 3.291 + 3.292 +# For backward compatibility 3.293 +check_gcc = $(warning check_gcc is deprecated - use cc-option) \ 3.294 + $(call cc-option, $(1),$(2)) 3.295 + 3.296 +# cc-option-yn 3.297 +# Usage: flag := $(call gcc-option-yn, -march=winchip-c6) 3.298 +cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ 3.299 + > /dev/null 2>&1; then echo "y"; else echo "n"; fi;) 3.300 + 3.301 +# cc-version 3.302 +# Usage gcc-ver := $(call cc-version $(CC)) 3.303 +cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \ 3.304 + $(if $(1), $(1), $(CC))) 3.305 + 3.306 + 3.307 +# Look for make include files relative to root of kernel src 3.308 +MAKEFLAGS += --include-dir=$(srctree) 3.309 + 3.310 +# For maximum performance (+ possibly random breakage, uncomment 3.311 +# the following) 3.312 + 3.313 +#MAKEFLAGS += -rR 3.314 + 3.315 +# Make variables (CC, etc...) 3.316 + 3.317 +AS = $(CROSS_COMPILE)as 3.318 +LD = $(CROSS_COMPILE)ld 3.319 +CC = $(CROSS_COMPILE)gcc 3.320 +CPP = $(CC) -E 3.321 +AR = $(CROSS_COMPILE)ar 3.322 +NM = $(CROSS_COMPILE)nm 3.323 +STRIP = $(CROSS_COMPILE)strip 3.324 +OBJCOPY = $(CROSS_COMPILE)objcopy 3.325 +OBJDUMP = $(CROSS_COMPILE)objdump 3.326 +AWK = awk 3.327 +GENKSYMS = scripts/genksyms/genksyms 3.328 +DEPMOD = /sbin/depmod 3.329 +KALLSYMS = scripts/kallsyms 3.330 +PERL = perl 3.331 +CHECK = sparse 3.332 +CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ 3.333 +MODFLAGS = -DMODULE 3.334 +CFLAGS_MODULE = $(MODFLAGS) 3.335 +AFLAGS_MODULE = $(MODFLAGS) 3.336 +LDFLAGS_MODULE = -r 3.337 +CFLAGS_KERNEL = 3.338 +AFLAGS_KERNEL = 3.339 + 3.340 +NOSTDINC_FLAGS = -nostdinc -iwithprefix include 3.341 + 3.342 +# Use LINUXINCLUDE when you must reference the include/ directory. 3.343 +# Needed to be compatible with the O= option 3.344 +LINUXINCLUDE := -Iinclude \ 3.345 + $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) 3.346 + 3.347 +CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) 3.348 + 3.349 +CFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs \ 3.350 + -fno-strict-aliasing -fno-common 3.351 +AFLAGS := -D__ASSEMBLY__ 3.352 + 3.353 +export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION LOCALVERSION KERNELRELEASE \ 3.354 + ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ 3.355 + CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \ 3.356 + HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS 3.357 + 3.358 +export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS 3.359 +export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE 3.360 +export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE 3.361 + 3.362 +# When compiling out-of-tree modules, put MODVERDIR in the module 3.363 +# tree rather than in the kernel tree. The kernel tree might 3.364 +# even be read-only. 3.365 +export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions 3.366 + 3.367 +# The temporary file to save gcc -MD generated dependencies must not 3.368 +# contain a comma 3.369 +comma := , 3.370 +depfile = $(subst $(comma),_,$(@D)/.$(@F).d) 3.371 + 3.372 +# Files to ignore in find ... statements 3.373 + 3.374 +RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc \) -prune -o 3.375 +RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc 3.376 + 3.377 +# =========================================================================== 3.378 +# Rules shared between *config targets and build targets 3.379 + 3.380 +# Basic helpers built in scripts/ 3.381 +.PHONY: scripts_basic 3.382 +scripts_basic: 3.383 + $(Q)$(MAKE) $(build)=scripts/basic 3.384 + 3.385 +# To make sure we do not include .config for any of the *config targets 3.386 +# catch them early, and hand them over to scripts/kconfig/Makefile 3.387 +# It is allowed to specify more targets when calling make, including 3.388 +# mixing *config targets and build targets. 3.389 +# For example 'make oldconfig all'. 3.390 +# Detect when mixed targets is specified, and make a second invocation 3.391 +# of make so .config is not included in this case either (for *config). 3.392 + 3.393 +no-dot-config-targets := clean mrproper distclean \ 3.394 + cscope TAGS tags help %docs check% 3.395 + 3.396 +config-targets := 0 3.397 +mixed-targets := 0 3.398 +dot-config := 1 3.399 + 3.400 +ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) 3.401 + ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) 3.402 + dot-config := 0 3.403 + endif 3.404 +endif 3.405 + 3.406 +ifeq ($(KBUILD_EXTMOD),) 3.407 + ifneq ($(filter config %config,$(MAKECMDGOALS)),) 3.408 + config-targets := 1 3.409 + ifneq ($(filter-out config %config,$(MAKECMDGOALS)),) 3.410 + mixed-targets := 1 3.411 + endif 3.412 + endif 3.413 +endif 3.414 + 3.415 +ifeq ($(mixed-targets),1) 3.416 +# =========================================================================== 3.417 +# We're called with mixed targets (*config and build targets). 3.418 +# Handle them one by one. 3.419 + 3.420 +%:: FORCE 3.421 + $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@ 3.422 + 3.423 +else 3.424 +ifeq ($(config-targets),1) 3.425 +# =========================================================================== 3.426 +# *config targets only - make sure prerequisites are updated, and descend 3.427 +# in scripts/kconfig to make the *config target 3.428 + 3.429 +config: scripts_basic FORCE 3.430 + $(Q)$(MAKE) $(build)=scripts/kconfig $@ 3.431 +%config: scripts_basic FORCE 3.432 + $(Q)$(MAKE) $(build)=scripts/kconfig $@ 3.433 + 3.434 +else 3.435 +# =========================================================================== 3.436 +# Build targets only - this includes vmlinux, arch specific targets, clean 3.437 +# targets and others. In general all targets except *config targets. 3.438 + 3.439 +ifeq ($(KBUILD_EXTMOD),) 3.440 +# Additional helpers built in scripts/ 3.441 +# Carefully list dependencies so we do not try to build scripts twice 3.442 +# in parrallel 3.443 +.PHONY: scripts 3.444 +scripts: scripts_basic include/config/MARKER 3.445 + $(Q)$(MAKE) $(build)=$(@) 3.446 + 3.447 +scripts_basic: include/linux/autoconf.h 3.448 + 3.449 +# Objects we will link into vmlinux / subdirs we need to visit 3.450 +init-y := init/ 3.451 +drivers-y := drivers/ sound/ 3.452 +net-y := net/ 3.453 +libs-y := lib/ 3.454 +core-y := usr/ 3.455 +endif # KBUILD_EXTMOD 3.456 + 3.457 +ifeq ($(dot-config),1) 3.458 +# In this section, we need .config 3.459 + 3.460 +# Read in dependencies to all Kconfig* files, make sure to run 3.461 +# oldconfig if changes are detected. 3.462 +-include .config.cmd 3.463 + 3.464 +include .config 3.465 + 3.466 +# If .config needs to be updated, it will be done via the dependency 3.467 +# that autoconf has on .config. 3.468 +# To avoid any implicit rule to kick in, define an empty command 3.469 +.config: ; 3.470 + 3.471 +# If .config is newer than include/linux/autoconf.h, someone tinkered 3.472 +# with it and forgot to run make oldconfig 3.473 +include/linux/autoconf.h: .config 3.474 + $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig 3.475 +else 3.476 +# Dummy target needed, because used as prerequisite 3.477 +include/linux/autoconf.h: ; 3.478 +endif 3.479 + 3.480 +# The all: target is the default when no target is given on the 3.481 +# command line. 3.482 +# This allow a user to issue only 'make' to build a kernel including modules 3.483 +# Defaults vmlinux but it is usually overriden in the arch makefile 3.484 +all: vmlinux 3.485 + 3.486 +ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE 3.487 +CFLAGS += -Os 3.488 +else 3.489 +CFLAGS += -O2 3.490 +endif 3.491 + 3.492 +ifndef CONFIG_FRAME_POINTER 3.493 +CFLAGS += -fomit-frame-pointer 3.494 +endif 3.495 + 3.496 +ifdef CONFIG_DEBUG_INFO 3.497 +CFLAGS += -g 3.498 +endif 3.499 + 3.500 +# warn about C99 declaration after statement 3.501 +CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) 3.502 + 3.503 +include $(srctree)/arch/$(ARCH)/Makefile 3.504 + 3.505 +# Default kernel image to build when no specific target is given. 3.506 +# KBUILD_IMAGE may be overruled on the commandline or 3.507 +# set in the environment 3.508 +# Also any assingments in arch/$(ARCH)/Makefiel take precedence over 3.509 +# this default value 3.510 +export KBUILD_IMAGE ?= vmlinux 3.511 + 3.512 +# 3.513 +# INSTALL_PATH specifies where to place the updated kernel and system map 3.514 +# images. Uncomment if you want to place them anywhere other than root. 3.515 +# 3.516 + 3.517 +#export INSTALL_PATH=/boot 3.518 + 3.519 +# 3.520 +# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory 3.521 +# relocations required by build roots. This is not defined in the 3.522 +# makefile but the arguement can be passed to make if needed. 3.523 +# 3.524 + 3.525 +MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) 3.526 +export MODLIB 3.527 + 3.528 + 3.529 +ifeq ($(KBUILD_EXTMOD),) 3.530 +core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ 3.531 + 3.532 +vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ 3.533 + $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ 3.534 + $(net-y) $(net-m) $(libs-y) $(libs-m))) 3.535 + 3.536 +vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \ 3.537 + $(init-n) $(init-) \ 3.538 + $(core-n) $(core-) $(drivers-n) $(drivers-) \ 3.539 + $(net-n) $(net-) $(libs-n) $(libs-)))) 3.540 + 3.541 +init-y := $(patsubst %/, %/built-in.o, $(init-y)) 3.542 +core-y := $(patsubst %/, %/built-in.o, $(core-y)) 3.543 +drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)) 3.544 +net-y := $(patsubst %/, %/built-in.o, $(net-y)) 3.545 +libs-y1 := $(patsubst %/, %/lib.a, $(libs-y)) 3.546 +libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y)) 3.547 +libs-y := $(libs-y1) $(libs-y2) 3.548 + 3.549 +# Build vmlinux 3.550 +# --------------------------------------------------------------------------- 3.551 +# vmlinux is build from the objects selected by $(vmlinux-init) and 3.552 +# $(vmlinux-main). Most are built-in.o files from top-level directories 3.553 +# in the kernel tree, others are specified in arch/$(ARCH)Makefile. 3.554 +# Ordering when linking is important, and $(vmlinux-init) must be first. 3.555 +# 3.556 +# vmlinux 3.557 +# ^ 3.558 +# | 3.559 +# +-< $(vmlinux-init) 3.560 +# | +--< init/version.o + more 3.561 +# | 3.562 +# +--< $(vmlinux-main) 3.563 +# | +--< driver/built-in.o mm/built-in.o + more 3.564 +# | 3.565 +# +-< kallsyms.o (see description in CONFIG_KALLSYMS section) 3.566 +# 3.567 +# vmlinux version (uname -v) cannot be updated during normal 3.568 +# descending-into-subdirs phase since we do not yet know if we need to 3.569 +# update vmlinux. 3.570 +# Therefore this step is delayed until just before final link of vmlinux - 3.571 +# except in the kallsyms case where it is done just before adding the 3.572 +# symbols to the kernel. 3.573 +# 3.574 +# System.map is generated to document addresses of all kernel symbols 3.575 + 3.576 +vmlinux-init := $(head-y) $(init-y) 3.577 +vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y) 3.578 +vmlinux-all := $(vmlinux-init) $(vmlinux-main) 3.579 +vmlinux-lds := arch/$(ARCH)/kernel/vmlinux.lds 3.580 + 3.581 +# Rule to link vmlinux - also used during CONFIG_KALLSYMS 3.582 +# May be overridden by arch/$(ARCH)/Makefile 3.583 +quiet_cmd_vmlinux__ ?= LD $@ 3.584 + cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \ 3.585 + -T $(vmlinux-lds) $(vmlinux-init) \ 3.586 + --start-group $(vmlinux-main) --end-group \ 3.587 + $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^) 3.588 + 3.589 +# Generate new vmlinux version 3.590 +quiet_cmd_vmlinux_version = GEN .version 3.591 + cmd_vmlinux_version = set -e; \ 3.592 + . $(srctree)/scripts/mkversion > .tmp_version; \ 3.593 + mv -f .tmp_version .version; \ 3.594 + $(MAKE) $(build)=init 3.595 + 3.596 +# Generate System.map 3.597 +quiet_cmd_sysmap = SYSMAP 3.598 + cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap 3.599 + 3.600 +# Link of vmlinux 3.601 +# If CONFIG_KALLSYMS is set .version is already updated 3.602 +# Generate System.map and verify that the content is consistent 3.603 + 3.604 +define rule_vmlinux__ 3.605 + $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version)) 3.606 + 3.607 + $(call cmd,vmlinux__) 3.608 + $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd 3.609 + 3.610 + $(Q)$(if $($(quiet)cmd_sysmap), \ 3.611 + echo ' $($(quiet)cmd_sysmap) System.map' &&) \ 3.612 + $(cmd_sysmap) $@ System.map; \ 3.613 + if [ $$? -ne 0 ]; then \ 3.614 + rm -f $@; \ 3.615 + /bin/false; \ 3.616 + fi; 3.617 + $(verify_kallsyms) 3.618 +endef 3.619 + 3.620 + 3.621 +ifdef CONFIG_KALLSYMS 3.622 +# Generate section listing all symbols and add it into vmlinux $(kallsyms.o) 3.623 +# It's a three stage process: 3.624 +# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is 3.625 +# empty 3.626 +# Running kallsyms on that gives us .tmp_kallsyms1.o with 3.627 +# the right size - vmlinux version (uname -v) is updated during this step 3.628 +# o .tmp_vmlinux2 now has a __kallsyms section of the right size, 3.629 +# but due to the added section, some addresses have shifted. 3.630 +# From here, we generate a correct .tmp_kallsyms2.o 3.631 +# o The correct .tmp_kallsyms2.o is linked into the final vmlinux. 3.632 +# o Verify that the System.map from vmlinux matches the map from 3.633 +# .tmp_vmlinux2, just in case we did not generate kallsyms correctly. 3.634 +# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using 3.635 +# .tmp_vmlinux3 and .tmp_kallsyms3.o. This is only meant as a 3.636 +# temporary bypass to allow the kernel to be built while the 3.637 +# maintainers work out what went wrong with kallsyms. 3.638 + 3.639 +ifdef CONFIG_KALLSYMS_EXTRA_PASS 3.640 +last_kallsyms := 3 3.641 +else 3.642 +last_kallsyms := 2 3.643 +endif 3.644 + 3.645 +kallsyms.o := .tmp_kallsyms$(last_kallsyms).o 3.646 + 3.647 +define verify_kallsyms 3.648 + $(Q)$(if $($(quiet)cmd_sysmap), \ 3.649 + echo ' $($(quiet)cmd_sysmap) .tmp_System.map' &&) \ 3.650 + $(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map 3.651 + $(Q)cmp -s System.map .tmp_System.map || \ 3.652 + (echo Inconsistent kallsyms data; \ 3.653 + echo Try setting CONFIG_KALLSYMS_EXTRA_PASS; \ 3.654 + rm .tmp_kallsyms* ; /bin/false ) 3.655 +endef 3.656 + 3.657 +# Update vmlinux version before link 3.658 +# Use + in front of this rule to silent warning about make -j1 3.659 +cmd_ksym_ld = $(cmd_vmlinux__) 3.660 +define rule_ksym_ld 3.661 + +$(call cmd,vmlinux_version) 3.662 + $(call cmd,vmlinux__) 3.663 + $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd 3.664 +endef 3.665 + 3.666 +# Generate .S file with all kernel symbols 3.667 +quiet_cmd_kallsyms = KSYM $@ 3.668 + cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \ 3.669 + $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@ 3.670 + 3.671 +.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE 3.672 + $(call if_changed_dep,as_o_S) 3.673 + 3.674 +.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS) 3.675 + $(call cmd,kallsyms) 3.676 + 3.677 +# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version 3.678 +.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE 3.679 + $(call if_changed_rule,ksym_ld) 3.680 + 3.681 +.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE 3.682 + $(call if_changed,vmlinux__) 3.683 + 3.684 +.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE 3.685 + $(call if_changed,vmlinux__) 3.686 + 3.687 +# Needs to visit scripts/ before $(KALLSYMS) can be used. 3.688 +$(KALLSYMS): scripts ; 3.689 + 3.690 +endif # ifdef CONFIG_KALLSYMS 3.691 + 3.692 +# vmlinux image - including updated kernel symbols 3.693 +vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE 3.694 + $(call if_changed_rule,vmlinux__) 3.695 + 3.696 +# The actual objects are generated when descending, 3.697 +# make sure no implicit rule kicks in 3.698 +$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ; 3.699 + 3.700 +# Handle descending into subdirectories listed in $(vmlinux-dirs) 3.701 +# Preset locale variables to speed up the build process. Limit locale 3.702 +# tweaks to this spot to avoid wrong language settings when running 3.703 +# make menuconfig etc. 3.704 +# Error messages still appears in the original language 3.705 + 3.706 +.PHONY: $(vmlinux-dirs) 3.707 +$(vmlinux-dirs): prepare-all scripts 3.708 + $(Q)$(MAKE) $(build)=$@ 3.709 + 3.710 +# Things we need to do before we recursively start building the kernel 3.711 +# or the modules are listed in "prepare-all". 3.712 +# A multi level approach is used. prepare1 is updated first, then prepare0. 3.713 +# prepare-all is the collection point for the prepare targets. 3.714 + 3.715 +.PHONY: prepare-all prepare prepare0 prepare1 prepare2 3.716 + 3.717 +# prepare 2 generate Makefile to be placed in output directory, if 3.718 +# using a seperate output directory. This allows convinient use 3.719 +# of make in output directory 3.720 +prepare2: 3.721 + $(Q)if /usr/bin/env test ! $(srctree) -ef $(objtree); then \ 3.722 + $(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \ 3.723 + $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) \ 3.724 + > $(objtree)/Makefile; \ 3.725 + fi 3.726 + 3.727 +# prepare1 is used to check if we are building in a separate output directory, 3.728 +# and if so do: 3.729 +# 1) Check that make has not been executed in the kernel src $(srctree) 3.730 +# 2) Create the include2 directory, used for the second asm symlink 3.731 + 3.732 +prepare1: prepare2 3.733 +ifneq ($(KBUILD_SRC),) 3.734 + @echo ' Using $(srctree) as source for kernel' 3.735 + $(Q)if [ -h $(srctree)/include/asm -o -f $(srctree)/.config ]; then \ 3.736 + echo " $(srctree) is not clean, please run 'make mrproper'";\ 3.737 + echo " in the '$(srctree)' directory.";\ 3.738 + /bin/false; \ 3.739 + fi; 3.740 + $(Q)if [ ! -d include2 ]; then mkdir -p include2; fi; 3.741 + $(Q)ln -fsn $(srctree)/include/asm-$(ARCH) include2/asm 3.742 +endif 3.743 + 3.744 +prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER 3.745 +ifneq ($(KBUILD_MODULES),) 3.746 + $(Q)rm -rf $(MODVERDIR) 3.747 + $(Q)mkdir -p $(MODVERDIR) 3.748 +endif 3.749 + 3.750 +# All the preparing.. 3.751 +prepare-all: prepare0 prepare 3.752 + 3.753 +# Leave this as default for preprocessing vmlinux.lds.S, which is now 3.754 +# done in arch/$(ARCH)/kernel/Makefile 3.755 + 3.756 +export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) 3.757 + 3.758 +# Single targets 3.759 +# --------------------------------------------------------------------------- 3.760 + 3.761 +%.s: %.c scripts FORCE 3.762 + $(Q)$(MAKE) $(build)=$(@D) $@ 3.763 +%.i: %.c scripts FORCE 3.764 + $(Q)$(MAKE) $(build)=$(@D) $@ 3.765 +%.o: %.c scripts FORCE 3.766 + $(Q)$(MAKE) $(build)=$(@D) $@ 3.767 +%/: scripts prepare FORCE 3.768 + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D) 3.769 +%.lst: %.c scripts FORCE 3.770 + $(Q)$(MAKE) $(build)=$(@D) $@ 3.771 +%.s: %.S scripts FORCE 3.772 + $(Q)$(MAKE) $(build)=$(@D) $@ 3.773 +%.o: %.S scripts FORCE 3.774 + $(Q)$(MAKE) $(build)=$(@D) $@ 3.775 + 3.776 +# FIXME: The asm symlink changes when $(ARCH) changes. That's 3.777 +# hard to detect, but I suppose "make mrproper" is a good idea 3.778 +# before switching between archs anyway. 3.779 + 3.780 +include/asm: 3.781 + @echo ' SYMLINK $@ -> include/asm-$(ARCH)' 3.782 + $(Q)if [ ! -d include ]; then mkdir -p include; fi; 3.783 + @ln -fsn asm-$(ARCH) $@ 3.784 + 3.785 +# Split autoconf.h into include/linux/config/* 3.786 + 3.787 +include/config/MARKER: include/linux/autoconf.h 3.788 + @echo ' SPLIT include/linux/autoconf.h -> include/config/*' 3.789 + @scripts/basic/split-include include/linux/autoconf.h include/config 3.790 + @touch $@ 3.791 + 3.792 +# Generate some files 3.793 +# --------------------------------------------------------------------------- 3.794 + 3.795 +# KERNELRELEASE can change from a few different places, meaning version.h 3.796 +# needs to be updated, so this check is forced on all builds 3.797 + 3.798 +uts_len := 64 3.799 + 3.800 +define filechk_version.h 3.801 + if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \ 3.802 + echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \ 3.803 + exit 1; \ 3.804 + fi; \ 3.805 + (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \ 3.806 + echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)`; \ 3.807 + echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'; \ 3.808 + ) 3.809 +endef 3.810 + 3.811 +include/linux/version.h: $(srctree)/Makefile FORCE 3.812 + $(call filechk,version.h) 3.813 + 3.814 +# --------------------------------------------------------------------------- 3.815 + 3.816 +.PHONY: depend dep 3.817 +depend dep: 3.818 + @echo '*** Warning: make $@ is unnecessary now.' 3.819 + 3.820 +# --------------------------------------------------------------------------- 3.821 +# Modules 3.822 + 3.823 +ifdef CONFIG_MODULES 3.824 + 3.825 +# By default, build modules as well 3.826 + 3.827 +all: modules 3.828 + 3.829 +# Build modules 3.830 + 3.831 +.PHONY: modules 3.832 +modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) 3.833 + @echo ' Building modules, stage 2.'; 3.834 + $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost 3.835 + 3.836 + 3.837 +# Target to prepare building external modules 3.838 +.PHONY: modules_prepare 3.839 +modules_prepare: prepare-all scripts 3.840 + 3.841 +# Target to install modules 3.842 +.PHONY: modules_install 3.843 +modules_install: _modinst_ _modinst_post 3.844 + 3.845 +.PHONY: _modinst_ 3.846 +_modinst_: 3.847 + @if [ -z "`$(DEPMOD) -V | grep module-init-tools`" ]; then \ 3.848 + echo "Warning: you may need to install module-init-tools"; \ 3.849 + echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\ 3.850 + sleep 1; \ 3.851 + fi 3.852 + @rm -rf $(MODLIB)/kernel 3.853 + @rm -f $(MODLIB)/source 3.854 + @mkdir -p $(MODLIB)/kernel 3.855 + @ln -s $(srctree) $(MODLIB)/source 3.856 + @if [ ! $(objtree) -ef $(MODLIB)/build ]; then \ 3.857 + rm -f $(MODLIB)/build ; \ 3.858 + ln -s $(objtree) $(MODLIB)/build ; \ 3.859 + fi 3.860 + $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst 3.861 + 3.862 +# If System.map exists, run depmod. This deliberately does not have a 3.863 +# dependency on System.map since that would run the dependency tree on 3.864 +# vmlinux. This depmod is only for convenience to give the initial 3.865 +# boot a modules.dep even before / is mounted read-write. However the 3.866 +# boot script depmod is the master version. 3.867 +ifeq "$(strip $(INSTALL_MOD_PATH))" "" 3.868 +depmod_opts := 3.869 +else 3.870 +depmod_opts := -b $(INSTALL_MOD_PATH) -r 3.871 +endif 3.872 +.PHONY: _modinst_post 3.873 +_modinst_post: _modinst_ 3.874 + if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi 3.875 + 3.876 +else # CONFIG_MODULES 3.877 + 3.878 +# Modules not configured 3.879 +# --------------------------------------------------------------------------- 3.880 + 3.881 +modules modules_install: FORCE 3.882 + @echo 3.883 + @echo "The present kernel configuration has modules disabled." 3.884 + @echo "Type 'make config' and enable loadable module support." 3.885 + @echo "Then build a kernel with module support enabled." 3.886 + @echo 3.887 + @exit 1 3.888 + 3.889 +endif # CONFIG_MODULES 3.890 + 3.891 +# Generate asm-offsets.h 3.892 +# --------------------------------------------------------------------------- 3.893 + 3.894 +define filechk_gen-asm-offsets 3.895 + (set -e; \ 3.896 + echo "#ifndef __ASM_OFFSETS_H__"; \ 3.897 + echo "#define __ASM_OFFSETS_H__"; \ 3.898 + echo "/*"; \ 3.899 + echo " * DO NOT MODIFY."; \ 3.900 + echo " *"; \ 3.901 + echo " * This file was generated by arch/$(ARCH)/Makefile"; \ 3.902 + echo " *"; \ 3.903 + echo " */"; \ 3.904 + echo ""; \ 3.905 + sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \ 3.906 + echo ""; \ 3.907 + echo "#endif" ) 3.908 +endef 3.909 + 3.910 + 3.911 +### 3.912 +# Cleaning is done on three levels. 3.913 +# make clean Delete most generated files 3.914 +# Leave enough to build external modules 3.915 +# make mrproper Delete the current configuration, and all generated files 3.916 +# make distclean Remove editor backup files, patch leftover files and the like 3.917 + 3.918 +# Directories & files removed with 'make clean' 3.919 +CLEAN_DIRS += $(MODVERDIR) 3.920 +CLEAN_FILES += vmlinux System.map \ 3.921 + .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map 3.922 + 3.923 +# Directories & files removed with 'make mrproper' 3.924 +MRPROPER_DIRS += include/config include2 3.925 +MRPROPER_FILES += .config .config.old include/asm .version \ 3.926 + include/linux/autoconf.h include/linux/version.h \ 3.927 + Module.symvers tags TAGS cscope* include/.asm-ignore 3.928 + 3.929 +# clean - Delete most, but leave enough to build external modules 3.930 +# 3.931 +clean: rm-dirs := $(CLEAN_DIRS) 3.932 +clean: rm-files := $(CLEAN_FILES) 3.933 +clean-dirs := $(addprefix _clean_,$(vmlinux-alldirs)) 3.934 + 3.935 +.PHONY: $(clean-dirs) clean archclean 3.936 +$(clean-dirs): 3.937 + $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) 3.938 + 3.939 +clean: archclean $(clean-dirs) 3.940 + $(call cmd,rmdirs) 3.941 + $(call cmd,rmfiles) 3.942 + @find . $(RCS_FIND_IGNORE) \ 3.943 + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ 3.944 + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \ 3.945 + -type f -print | xargs rm -f 3.946 + 3.947 +# mrproper - Delete all generated files, including .config 3.948 +# 3.949 +mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS)) 3.950 +mrproper: rm-files := $(wildcard $(MRPROPER_FILES)) 3.951 +mrproper-dirs := $(addprefix _mrproper_,Documentation/DocBook scripts) 3.952 + 3.953 +.PHONY: $(mrproper-dirs) mrproper archmrproper 3.954 +$(mrproper-dirs): 3.955 + $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@) 3.956 + 3.957 +mrproper: clean archmrproper $(mrproper-dirs) 3.958 + $(call cmd,rmdirs) 3.959 + $(call cmd,rmfiles) 3.960 + 3.961 +# distclean 3.962 +# 3.963 +.PHONY: distclean 3.964 + 3.965 +distclean: mrproper 3.966 + @find $(srctree) $(RCS_FIND_IGNORE) \ 3.967 + \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ 3.968 + -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ 3.969 + -o -name '.*.rej' -o -size 0 \ 3.970 + -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \ 3.971 + -type f -print | xargs rm -f 3.972 + 3.973 + 3.974 +# Packaging of the kernel to various formats 3.975 +# --------------------------------------------------------------------------- 3.976 +# rpm target kept for backward compatibility 3.977 +package-dir := $(srctree)/scripts/package 3.978 + 3.979 +.PHONY: %-pkg rpm 3.980 + 3.981 +%pkg: FORCE 3.982 + $(Q)$(MAKE) -f $(package-dir)/Makefile $@ 3.983 +rpm: FORCE 3.984 + $(Q)$(MAKE) -f $(package-dir)/Makefile $@ 3.985 + 3.986 + 3.987 +# Brief documentation of the typical targets used 3.988 +# --------------------------------------------------------------------------- 3.989 + 3.990 +boards := $(wildcard $(srctree)/arch/$(ARCH)/configs/*_defconfig) 3.991 +boards := $(notdir $(boards)) 3.992 + 3.993 +help: 3.994 + @echo 'Cleaning targets:' 3.995 + @echo ' clean - remove most generated files but keep the config' 3.996 + @echo ' mrproper - remove all generated files + config + various backup files' 3.997 + @echo '' 3.998 + @echo 'Configuration targets:' 3.999 + @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help 3.1000 + @echo '' 3.1001 + @echo 'Other generic targets:' 3.1002 + @echo ' all - Build all targets marked with [*]' 3.1003 + @echo '* vmlinux - Build the bare kernel' 3.1004 + @echo '* modules - Build all modules' 3.1005 + @echo ' modules_install - Install all modules' 3.1006 + @echo ' dir/ - Build all files in dir and below' 3.1007 + @echo ' dir/file.[ois] - Build specified target only' 3.1008 + @echo ' rpm - Build a kernel as an RPM package' 3.1009 + @echo ' tags/TAGS - Generate tags file for editors' 3.1010 + @echo ' cscope - Generate cscope index' 3.1011 + @echo '' 3.1012 + @echo 'Static analysers' 3.1013 + @echo ' buildcheck - List dangling references to vmlinux discarded sections' 3.1014 + @echo ' and init sections from non-init sections' 3.1015 + @echo ' checkstack - Generate a list of stack hogs' 3.1016 + @echo ' namespacecheck - Name space analysis on compiled kernel' 3.1017 + @echo '' 3.1018 + @echo 'Kernel packaging:' 3.1019 + @$(MAKE) -f $(package-dir)/Makefile help 3.1020 + @echo '' 3.1021 + @echo 'Documentation targets:' 3.1022 + @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp 3.1023 + @echo '' 3.1024 + @echo 'Architecture specific targets ($(ARCH)):' 3.1025 + @$(if $(archhelp),$(archhelp),\ 3.1026 + echo ' No architecture specific help defined for $(ARCH)') 3.1027 + @echo '' 3.1028 + @$(if $(boards), \ 3.1029 + $(foreach b, $(boards), \ 3.1030 + printf " %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \ 3.1031 + echo '') 3.1032 + 3.1033 + @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' 3.1034 + @echo ' make O=dir [targets] Locate all output files in "dir", including .config' 3.1035 + @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse)' 3.1036 + @echo ' make C=2 [targets] Force check of all c source with $$CHECK (sparse)' 3.1037 + @echo '' 3.1038 + @echo 'Execute "make" or "make all" to build all targets marked with [*] ' 3.1039 + @echo 'For further info see the ./README file' 3.1040 + 3.1041 + 3.1042 +# Documentation targets 3.1043 +# --------------------------------------------------------------------------- 3.1044 +%docs: scripts_basic FORCE 3.1045 + $(Q)$(MAKE) $(build)=Documentation/DocBook $@ 3.1046 + 3.1047 +else # KBUILD_EXTMOD 3.1048 + 3.1049 +### 3.1050 +# External module support. 3.1051 +# When building external modules the kernel used as basis is considered 3.1052 +# read-only, and no consistency checks are made and the make 3.1053 +# system is not used on the basis kernel. If updates are required 3.1054 +# in the basis kernel ordinary make commands (without M=...) must 3.1055 +# be used. 3.1056 +# 3.1057 +# The following are the only valid targets when building external 3.1058 +# modules. 3.1059 +# make M=dir clean Delete all automatically generated files 3.1060 +# make M=dir modules Make all modules in specified dir 3.1061 +# make M=dir Same as 'make M=dir modules' 3.1062 +# make M=dir modules_install 3.1063 +# Install the modules build in the module directory 3.1064 +# Assumes install directory is already created 3.1065 + 3.1066 +# We are always building modules 3.1067 +KBUILD_MODULES := 1 3.1068 +.PHONY: crmodverdir 3.1069 +crmodverdir: 3.1070 + $(Q)mkdir -p $(MODVERDIR) 3.1071 + 3.1072 +module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD)) 3.1073 +.PHONY: $(module-dirs) modules 3.1074 +$(module-dirs): crmodverdir 3.1075 + $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) 3.1076 + 3.1077 +modules: $(module-dirs) 3.1078 + @echo ' Building modules, stage 2.'; 3.1079 + $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost 3.1080 + 3.1081 +.PHONY: modules_install 3.1082 +modules_install: 3.1083 + $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst 3.1084 + 3.1085 +clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD)) 3.1086 + 3.1087 +.PHONY: $(clean-dirs) clean 3.1088 +$(clean-dirs): 3.1089 + $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) 3.1090 + 3.1091 +clean: rm-dirs := $(MODVERDIR) 3.1092 +clean: $(clean-dirs) 3.1093 + $(call cmd,rmdirs) 3.1094 + @find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \ 3.1095 + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ 3.1096 + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \ 3.1097 + -type f -print | xargs rm -f 3.1098 + 3.1099 +help: 3.1100 + @echo ' Building external modules.' 3.1101 + @echo ' Syntax: make -C path/to/kernel/src M=$$PWD target' 3.1102 + @echo '' 3.1103 + @echo ' modules - default target, build the module(s)' 3.1104 + @echo ' modules_install - install the module' 3.1105 + @echo ' clean - remove generated files in module directory only' 3.1106 + @echo '' 3.1107 +endif # KBUILD_EXTMOD 3.1108 + 3.1109 +# Generate tags for editors 3.1110 +# --------------------------------------------------------------------------- 3.1111 + 3.1112 +define all-sources 3.1113 + ( find $(srctree) $(RCS_FIND_IGNORE) \ 3.1114 + \( -name include -o -name arch \) -prune -o \ 3.1115 + -name '*.[chS]' -print; \ 3.1116 + find $(srctree)/arch/$(ARCH) $(RCS_FIND_IGNORE) \ 3.1117 + -name '*.[chS]' -print; \ 3.1118 + find $(srctree)/security/selinux/include $(RCS_FIND_IGNORE) \ 3.1119 + -name '*.[chS]' -print; \ 3.1120 + find $(srctree)/include $(RCS_FIND_IGNORE) \ 3.1121 + \( -name config -o -name 'asm-*' \) -prune \ 3.1122 + -o -name '*.[chS]' -print; \ 3.1123 + find $(srctree)/include/asm-$(ARCH) $(RCS_FIND_IGNORE) \ 3.1124 + -name '*.[chS]' -print; \ 3.1125 + find $(srctree)/include/asm-generic $(RCS_FIND_IGNORE) \ 3.1126 + -name '*.[chS]' -print ) 3.1127 +endef 3.1128 + 3.1129 +quiet_cmd_cscope-file = FILELST cscope.files 3.1130 + cmd_cscope-file = $(all-sources) > cscope.files 3.1131 + 3.1132 +quiet_cmd_cscope = MAKE cscope.out 3.1133 + cmd_cscope = cscope -k -b -q 3.1134 + 3.1135 +cscope: FORCE 3.1136 + $(call cmd,cscope-file) 3.1137 + $(call cmd,cscope) 3.1138 + 3.1139 +quiet_cmd_TAGS = MAKE $@ 3.1140 +cmd_TAGS = $(all-sources) | etags - 3.1141 + 3.1142 +# Exuberant ctags works better with -I 3.1143 + 3.1144 +quiet_cmd_tags = MAKE $@ 3.1145 +define cmd_tags 3.1146 + rm -f $@; \ 3.1147 + CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \ 3.1148 + $(all-sources) | xargs ctags $$CTAGSF -a 3.1149 +endef 3.1150 + 3.1151 +TAGS: FORCE 3.1152 + $(call cmd,TAGS) 3.1153 + 3.1154 +tags: FORCE 3.1155 + $(call cmd,tags) 3.1156 + 3.1157 + 3.1158 +# Scripts to check various things for consistency 3.1159 +# --------------------------------------------------------------------------- 3.1160 + 3.1161 +configcheck: 3.1162 + find * $(RCS_FIND_IGNORE) \ 3.1163 + -name '*.[hcS]' -type f -print | sort \ 3.1164 + | xargs $(PERL) -w scripts/checkconfig.pl 3.1165 + 3.1166 +includecheck: 3.1167 + find * $(RCS_FIND_IGNORE) \ 3.1168 + -name '*.[hcS]' -type f -print | sort \ 3.1169 + | xargs $(PERL) -w scripts/checkincludes.pl 3.1170 + 3.1171 +versioncheck: 3.1172 + find * $(RCS_FIND_IGNORE) \ 3.1173 + -name '*.[hcS]' -type f -print | sort \ 3.1174 + | xargs $(PERL) -w scripts/checkversion.pl 3.1175 + 3.1176 +buildcheck: 3.1177 + $(PERL) $(srctree)/scripts/reference_discarded.pl 3.1178 + $(PERL) $(srctree)/scripts/reference_init.pl 3.1179 + 3.1180 +namespacecheck: 3.1181 + $(PERL) $(srctree)/scripts/namespace.pl 3.1182 + 3.1183 +endif #ifeq ($(config-targets),1) 3.1184 +endif #ifeq ($(mixed-targets),1) 3.1185 + 3.1186 +.PHONY: checkstack 3.1187 +checkstack: 3.1188 + $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \ 3.1189 + $(PERL) $(src)/scripts/checkstack.pl $(ARCH) 3.1190 + 3.1191 +# FIXME Should go into a make.lib or something 3.1192 +# =========================================================================== 3.1193 + 3.1194 +quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN $(wildcard $(rm-dirs))) 3.1195 + cmd_rmdirs = rm -rf $(rm-dirs) 3.1196 + 3.1197 +quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files))) 3.1198 + cmd_rmfiles = rm -f $(rm-files) 3.1199 + 3.1200 + 3.1201 +a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \ 3.1202 + $(NOSTDINC_FLAGS) $(CPPFLAGS) \ 3.1203 + $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o) 3.1204 + 3.1205 +quiet_cmd_as_o_S = AS $@ 3.1206 +cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< 3.1207 + 3.1208 +# read all saved command lines 3.1209 + 3.1210 +targets := $(wildcard $(sort $(targets))) 3.1211 +cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) 3.1212 + 3.1213 +ifneq ($(cmd_files),) 3.1214 + $(cmd_files): ; # Do not try to update included dependency files 3.1215 + include $(cmd_files) 3.1216 +endif 3.1217 + 3.1218 +# Execute command and generate cmd file 3.1219 +if_changed = $(if $(strip $? \ 3.1220 + $(filter-out $(cmd_$(1)),$(cmd_$@))\ 3.1221 + $(filter-out $(cmd_$@),$(cmd_$(1)))),\ 3.1222 + @set -e; \ 3.1223 + $(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \ 3.1224 + $(cmd_$(1)); \ 3.1225 + echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd) 3.1226 + 3.1227 + 3.1228 +# execute the command and also postprocess generated .d dependencies 3.1229 +# file 3.1230 +if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\ 3.1231 + $(filter-out $(cmd_$(1)),$(cmd_$@))\ 3.1232 + $(filter-out $(cmd_$@),$(cmd_$(1)))),\ 3.1233 + $(Q)set -e; \ 3.1234 + $(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \ 3.1235 + $(cmd_$(1)); \ 3.1236 + scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \ 3.1237 + rm -f $(depfile); \ 3.1238 + mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd) 3.1239 + 3.1240 +# Usage: $(call if_changed_rule,foo) 3.1241 +# will check if $(cmd_foo) changed, or any of the prequisites changed, 3.1242 +# and if so will execute $(rule_foo) 3.1243 + 3.1244 +if_changed_rule = $(if $(strip $? \ 3.1245 + $(filter-out $(cmd_$(1)),$(cmd_$(@F)))\ 3.1246 + $(filter-out $(cmd_$(@F)),$(cmd_$(1)))),\ 3.1247 + $(Q)$(rule_$(1))) 3.1248 + 3.1249 +# If quiet is set, only print short version of command 3.1250 + 3.1251 +cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) 3.1252 + 3.1253 +# filechk is used to check if the content of a generated file is updated. 3.1254 +# Sample usage: 3.1255 +# define filechk_sample 3.1256 +# echo $KERNELRELEASE 3.1257 +# endef 3.1258 +# version.h : Makefile 3.1259 +# $(call filechk,sample) 3.1260 +# The rule defined shall write to stdout the content of the new file. 3.1261 +# The existing file will be compared with the new one. 3.1262 +# - If no file exist it is created 3.1263 +# - If the content differ the new file is used 3.1264 +# - If they are equal no change, and no timestamp update 3.1265 + 3.1266 +define filechk 3.1267 + @set -e; \ 3.1268 + echo ' CHK $@'; \ 3.1269 + mkdir -p $(dir $@); \ 3.1270 + $(filechk_$(1)) < $< > $@.tmp; \ 3.1271 + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ 3.1272 + rm -f $@.tmp; \ 3.1273 + else \ 3.1274 + echo ' UPD $@'; \ 3.1275 + mv -f $@.tmp $@; \ 3.1276 + fi 3.1277 +endef 3.1278 + 3.1279 +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=dir 3.1280 +# Usage: 3.1281 +# $(Q)$(MAKE) $(build)=dir 3.1282 +build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj 3.1283 + 3.1284 +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir 3.1285 +# Usage: 3.1286 +# $(Q)$(MAKE) $(clean)=dir 3.1287 +clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj 3.1288 + 3.1289 +# $(call descend,<dir>,<target>) 3.1290 +# Recursively call a sub-make in <dir> with target <target> 3.1291 +# Usage is deprecated, because make does not see this as an invocation of make. 3.1292 +descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2) 3.1293 + 3.1294 +endif # skip-makefile 3.1295 + 3.1296 +FORCE:
4.1 --- a/linux-2.6.9-xen-sparse/arch/xen/Kconfig Wed Nov 24 11:51:49 2004 +0000 4.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/Kconfig Wed Nov 24 12:07:16 2004 +0000 4.3 @@ -49,6 +49,20 @@ config XEN_BLKDEV_BACKEND 4.4 block devices to other guests via a high-performance shared-memory 4.5 interface. 4.6 4.7 +if XEN_BLKDEV_BACKEND 4.8 +config XEN_BLKDEV_TAP_BE 4.9 + bool "Block Tap support for backend driver (DANGEROUS)" 4.10 + default n 4.11 + help 4.12 + If you intend to use the block tap driver, the backend domain will 4.13 + not know the domain id of the real frontend, and so will not be able 4.14 + to map its data pages. This modifies the backend to attempt to map 4.15 + from both the tap domain and the real frontend. This presents a 4.16 + security risk, and so should ONLY be used for development 4.17 + with the blktap. This option will be removed as the block drivers are 4.18 + modified to use grant tables. 4.19 +endif 4.20 + 4.21 config XEN_NETDEV_BACKEND 4.22 bool "Network-device backend driver" 4.23 default y if XEN_PHYSDEV_ACCESS 4.24 @@ -94,6 +108,16 @@ config XEN_NETDEV_FRONTEND_PIPELINED_TRA 4.25 enabled; then you must say N here. 4.26 endif 4.27 4.28 +config XEN_BLKDEV_TAP 4.29 + bool "Block device tap driver" 4.30 + default n 4.31 + help 4.32 + This driver allows a VM to interact on block device channels 4.33 + to other VMs. Block messages may be passed through or redirected 4.34 + to a character device, allowing device prototyping in application 4.35 + space. Odds are that you want to say N here. 4.36 + 4.37 + 4.38 config XEN_WRITABLE_PAGETABLES 4.39 bool 4.40 default y
5.1 --- a/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig Wed Nov 24 11:51:49 2004 +0000 5.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig Wed Nov 24 12:07:16 2004 +0000 5.3 @@ -13,9 +13,11 @@ CONFIG_NO_IDLE_HZ=y 5.4 CONFIG_XEN_PRIVILEGED_GUEST=y 5.5 CONFIG_XEN_PHYSDEV_ACCESS=y 5.6 CONFIG_XEN_BLKDEV_BACKEND=y 5.7 +# CONFIG_XEN_BLKDEV_TAP_BE is not set 5.8 CONFIG_XEN_NETDEV_BACKEND=y 5.9 CONFIG_XEN_BLKDEV_FRONTEND=y 5.10 CONFIG_XEN_NETDEV_FRONTEND=y 5.11 +# CONFIG_XEN_BLKDEV_TAP is not set 5.12 # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set 5.13 CONFIG_XEN_WRITABLE_PAGETABLES=y 5.14 CONFIG_XEN_SCRUB_PAGES=y
6.1 --- a/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig Wed Nov 24 11:51:49 2004 +0000 6.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig Wed Nov 24 12:07:16 2004 +0000 6.3 @@ -13,9 +13,11 @@ CONFIG_NO_IDLE_HZ=y 6.4 # CONFIG_XEN_PRIVILEGED_GUEST is not set 6.5 # CONFIG_XEN_PHYSDEV_ACCESS is not set 6.6 # CONFIG_XEN_BLKDEV_BACKEND is not set 6.7 +# CONFIG_XEN_BLKDEV_TAP_BE is not set 6.8 # CONFIG_XEN_NETDEV_BACKEND is not set 6.9 CONFIG_XEN_BLKDEV_FRONTEND=y 6.10 CONFIG_XEN_NETDEV_FRONTEND=y 6.11 +# CONFIG_XEN_BLKDEV_TAP is not set 6.12 # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set 6.13 CONFIG_XEN_WRITABLE_PAGETABLES=y 6.14 CONFIG_XEN_SCRUB_PAGES=y
7.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/Makefile Wed Nov 24 11:51:49 2004 +0000 7.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/Makefile Wed Nov 24 12:07:16 2004 +0000 7.3 @@ -9,4 +9,5 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND) += blkb 7.4 obj-$(CONFIG_XEN_NETDEV_BACKEND) += netback/ 7.5 obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += blkfront/ 7.6 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += netfront/ 7.7 +obj-$(CONFIG_XEN_BLKDEV_TAP) += blktap/ 7.8
8.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c Wed Nov 24 11:51:49 2004 +0000 8.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c Wed Nov 24 12:07:16 2004 +0000 8.3 @@ -69,6 +69,19 @@ static PEND_RING_IDX pending_prod, pendi 8.4 static kmem_cache_t *buffer_head_cachep; 8.5 #endif 8.6 8.7 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE 8.8 +/* 8.9 + * If the tap driver is used, we may get pages belonging to either the tap 8.10 + * or (more likely) the real frontend. The backend must specify which domain 8.11 + * a given page belongs to in update_va_mapping though. For the moment, 8.12 + * we pass in the domid of the real frontend in PROBE messages and store 8.13 + * this value in alt_dom. Then on mapping, we try both. This is a Guiness 8.14 + * book of records-calibre grim hack, and represents a bit of a security risk. 8.15 + * Grant tables will soon solve the problem though! 8.16 + */ 8.17 +static domid_t alt_dom = 0; 8.18 +#endif 8.19 + 8.20 static int do_block_io_op(blkif_t *blkif, int max_to_do); 8.21 static void dispatch_probe(blkif_t *blkif, blkif_request_t *req); 8.22 static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req); 8.23 @@ -324,12 +337,27 @@ static void dispatch_probe(blkif_t *blki 8.24 (blkif_last_sect(req->frame_and_sects[0]) != 7) ) 8.25 goto out; 8.26 8.27 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE 8.28 + /* Grab the real frontend out of the probe message. */ 8.29 + alt_dom = (domid_t)req->frame_and_sects[1]; 8.30 +#endif 8.31 + 8.32 if ( HYPERVISOR_update_va_mapping_otherdomain( 8.33 MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT, 8.34 (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL }, 8.35 - 0, blkif->domid) ) 8.36 + 0, blkif->domid) ) { 8.37 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE 8.38 + /* That didn't work. Try alt_dom. */ 8.39 + if ( HYPERVISOR_update_va_mapping_otherdomain( 8.40 + MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT, 8.41 + (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL }, 8.42 + 0, alt_dom) ) 8.43 + goto out; 8.44 +#else 8.45 goto out; 8.46 - 8.47 +#endif 8.48 + } 8.49 + 8.50 rsp = vbd_probe(blkif, (vdisk_t *)MMAP_VADDR(pending_idx, 0), 8.51 PAGE_SIZE / sizeof(vdisk_t)); 8.52 8.53 @@ -412,8 +440,11 @@ static void dispatch_rw_block_io(blkif_t 8.54 mcl[i].args[0] = MMAP_VADDR(pending_idx, i) >> PAGE_SHIFT; 8.55 mcl[i].args[1] = (phys_seg[i].buffer & PAGE_MASK) | remap_prot; 8.56 mcl[i].args[2] = 0; 8.57 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE 8.58 + mcl[i].args[3] = (alt_dom != 0) ? alt_dom : blkif->domid; 8.59 +#else 8.60 mcl[i].args[3] = blkif->domid; 8.61 - 8.62 +#endif 8.63 phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] = 8.64 FOREIGN_FRAME(phys_seg[i].buffer >> PAGE_SHIFT); 8.65 } 8.66 @@ -580,7 +611,10 @@ static int __init blkif_init(void) 8.67 #endif 8.68 8.69 blkif_ctrlif_init(); 8.70 - 8.71 + 8.72 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE 8.73 + printk(KERN_ALERT "NOTE: Blkif backend is running with tap support on!\n"); 8.74 +#endif 8.75 return 0; 8.76 } 8.77
9.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c Wed Nov 24 11:51:49 2004 +0000 9.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c Wed Nov 24 12:07:16 2004 +0000 9.3 @@ -1263,7 +1263,8 @@ static void blkif_status(blkif_fe_interf 9.4 { 9.5 if ( status->handle != blkif_handle ) 9.6 { 9.7 - WPRINTK(" Invalid blkif: handle=%u", status->handle); 9.8 + WPRINTK(" Invalid blkif: handle=%u\n", status->handle); 9.9 + unexpected(status); 9.10 return; 9.11 } 9.12
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/Makefile Wed Nov 24 12:07:16 2004 +0000 10.3 @@ -0,0 +1,3 @@ 10.4 + 10.5 +obj-y := blktap_userdev.o blktap_datapath.o blktap_controlmsg.o blktap.o 10.6 +
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.c Wed Nov 24 12:07:16 2004 +0000 11.3 @@ -0,0 +1,86 @@ 11.4 +/****************************************************************************** 11.5 + * blktap.c 11.6 + * 11.7 + * XenLinux virtual block-device tap. 11.8 + * 11.9 + * Copyright (c) 2004, Andrew Warfield 11.10 + * 11.11 + * Based on the original split block driver: 11.12 + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand 11.13 + * Modifications by Mark A. Williamson are (c) Intel Research Cambridge 11.14 + * Copyright (c) 2004, Christian Limpach 11.15 + * 11.16 + * Note that unlike the split block driver code, this driver has been developed 11.17 + * strictly for Linux 2.6 11.18 + */ 11.19 + 11.20 +#include "blktap.h" 11.21 + 11.22 +int __init xlblk_init(void) 11.23 +{ 11.24 + ctrl_msg_t cmsg; 11.25 + blkif_fe_driver_status_t fe_st; 11.26 + blkif_be_driver_status_t be_st; 11.27 + 11.28 + printk(KERN_INFO "Initialising Xen block tap device\n"); 11.29 + 11.30 + DPRINTK(" tap - Backend connection init:\n"); 11.31 + 11.32 + 11.33 + (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx, 11.34 + CALLBACK_IN_BLOCKING_CONTEXT); 11.35 + 11.36 + /* Send a driver-UP notification to the domain controller. */ 11.37 + cmsg.type = CMSG_BLKIF_FE; 11.38 + cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS; 11.39 + cmsg.length = sizeof(blkif_fe_driver_status_t); 11.40 + fe_st.status = BLKIF_DRIVER_STATUS_UP; 11.41 + memcpy(cmsg.msg, &fe_st, sizeof(fe_st)); 11.42 + ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); 11.43 + 11.44 + DPRINTK(" tap - Frontend connection init:\n"); 11.45 + 11.46 + active_reqs_init(); 11.47 + 11.48 + ptfe_blkif.status = DISCONNECTED; 11.49 + 11.50 + (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, 11.51 + CALLBACK_IN_BLOCKING_CONTEXT); 11.52 + 11.53 + /* Send a driver-UP notification to the domain controller. */ 11.54 + cmsg.type = CMSG_BLKIF_BE; 11.55 + cmsg.subtype = CMSG_BLKIF_BE_DRIVER_STATUS; 11.56 + cmsg.length = sizeof(blkif_be_driver_status_t); 11.57 + be_st.status = BLKIF_DRIVER_STATUS_UP; 11.58 + memcpy(cmsg.msg, &be_st, sizeof(be_st)); 11.59 + ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); 11.60 + 11.61 + DPRINTK(" tap - Userland channel init:\n"); 11.62 + 11.63 + blktap_init(); 11.64 + 11.65 + DPRINTK("Blkif tap device initialized.\n"); 11.66 + 11.67 + return 0; 11.68 +} 11.69 + 11.70 +void blkdev_suspend(void) 11.71 +{ 11.72 +} 11.73 + 11.74 +void blkdev_resume(void) 11.75 +{ 11.76 + ctrl_msg_t cmsg; 11.77 + blkif_fe_driver_status_t st; 11.78 + 11.79 + /* Send a driver-UP notification to the domain controller. */ 11.80 + cmsg.type = CMSG_BLKIF_FE; 11.81 + cmsg.subtype = CMSG_BLKIF_FE_DRIVER_STATUS; 11.82 + cmsg.length = sizeof(blkif_fe_driver_status_t); 11.83 + st.status = BLKIF_DRIVER_STATUS_UP; 11.84 + memcpy(cmsg.msg, &st, sizeof(st)); 11.85 + ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); 11.86 +} 11.87 + 11.88 + 11.89 +__initcall(xlblk_init);
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.h Wed Nov 24 12:07:16 2004 +0000 12.3 @@ -0,0 +1,254 @@ 12.4 +/* 12.5 + * blktap.h 12.6 + * 12.7 + * Interfaces for the Xen block tap driver. 12.8 + * 12.9 + * (c) 2004, Andrew Warfield, University of Cambridge 12.10 + * 12.11 + */ 12.12 + 12.13 +#ifndef __BLKTAP_H__ 12.14 +#define __BLKTAP_H__ 12.15 + 12.16 +#include <linux/version.h> 12.17 +#include <linux/blkdev.h> 12.18 +#include <linux/config.h> 12.19 +#include <linux/sched.h> 12.20 +#include <linux/interrupt.h> 12.21 +#include <asm-xen/ctrl_if.h> 12.22 +#include <linux/slab.h> 12.23 +#include <linux/blkdev.h> 12.24 +#include <asm/io.h> 12.25 +#include <asm/setup.h> 12.26 +#include <asm/pgalloc.h> 12.27 +#include <asm-xen/hypervisor.h> 12.28 +#include <asm-xen/xen-public/io/blkif.h> 12.29 + 12.30 +/* -------[ debug / pretty printing ]--------------------------------- */ 12.31 + 12.32 +#if 0 12.33 +#define ASSERT(_p) \ 12.34 + if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ 12.35 + __LINE__, __FILE__); *(int*)0=0; } 12.36 +#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ 12.37 + __FILE__ , __LINE__ , ## _a ) 12.38 +#else 12.39 +#define ASSERT(_p) ((void)0) 12.40 +#define DPRINTK(_f, _a...) ((void)0) 12.41 +#endif 12.42 + 12.43 +#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args) 12.44 + 12.45 +/* -------[ connection / request tracking ]--------------------------- */ 12.46 + 12.47 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 12.48 +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) 12.49 +#endif 12.50 + 12.51 +extern spinlock_t blkif_io_lock; 12.52 + 12.53 +typedef struct blkif_st { 12.54 + /* Unique identifier for this interface. */ 12.55 + domid_t domid; 12.56 + unsigned int handle; 12.57 + /* Physical parameters of the comms window. */ 12.58 + unsigned long shmem_frame; 12.59 + unsigned int evtchn; 12.60 + int irq; 12.61 + /* Comms information. */ 12.62 + blkif_ring_t *blk_ring_base; /* ioremap()'ed ptr to shmem_frame. */ 12.63 + BLKIF_RING_IDX blk_req_cons; /* Request consumer. */ 12.64 + BLKIF_RING_IDX blk_resp_prod; /* Private version of resp. producer. */ 12.65 + 12.66 + enum { DISCONNECTED, DISCONNECTING, CONNECTED } status; 12.67 + /* 12.68 + * DISCONNECT response is deferred until pending requests are ack'ed. 12.69 + * We therefore need to store the id from the original request. 12.70 + */ u8 disconnect_rspid; 12.71 + struct blkif_st *hash_next; 12.72 + struct list_head blkdev_list; 12.73 + spinlock_t blk_ring_lock; 12.74 + atomic_t refcnt; 12.75 + 12.76 + struct work_struct work; 12.77 +} blkif_t; 12.78 + 12.79 +typedef struct { 12.80 + blkif_t *blkif; 12.81 + unsigned long id; 12.82 + int nr_pages; 12.83 + unsigned long mach_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 12.84 + unsigned long virt_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 12.85 + int next_free; 12.86 +} active_req_t; 12.87 + 12.88 + 12.89 +/* -------[ block ring structs ]-------------------------------------- */ 12.90 + 12.91 +/* Types of ring. */ 12.92 +#define BLKIF_REQ_RING_TYPE 1 12.93 +#define BLKIF_RSP_RING_TYPE 2 12.94 + 12.95 +/* generic ring struct. */ 12.96 +typedef struct blkif_generic_ring_struct { 12.97 + int type; 12.98 +} blkif_generic_ring_t; 12.99 + 12.100 +/* A requestor's view of a ring. */ 12.101 +typedef struct blkif_req_ring_struct { 12.102 + 12.103 + int type; /* Will be BLKIF_REQ_RING_TYPE */ 12.104 + BLKIF_RING_IDX req_prod; /* PRIVATE req_prod index */ 12.105 + BLKIF_RING_IDX rsp_cons; /* Response consumer index */ 12.106 + blkif_ring_t *ring; /* Pointer to shared ring struct */ 12.107 + 12.108 +} blkif_req_ring_t; 12.109 + 12.110 +#define BLKIF_REQ_RING_INIT { BLKIF_REQ_RING_TYPE, 0, 0, 0 } 12.111 + 12.112 +/* A responder's view of a ring. */ 12.113 +typedef struct blkif_rsp_ring_struct { 12.114 + 12.115 + int type; 12.116 + BLKIF_RING_IDX rsp_prod; /* PRIVATE rsp_prod index */ 12.117 + BLKIF_RING_IDX req_cons; /* Request consumer index */ 12.118 + blkif_ring_t *ring; /* Pointer to shared ring struct */ 12.119 + 12.120 +} blkif_rsp_ring_t; 12.121 + 12.122 +#define BLKIF_RSP_RING_INIT = { BLKIF_RSP_RING_TYPE, 0, 0, 0 } 12.123 + 12.124 +#define RING(a) (blkif_generic_ring_t *)(a) 12.125 + 12.126 +inline int BLKTAP_RING_FULL(blkif_generic_ring_t *ring); 12.127 + 12.128 + 12.129 +/* -------[ interposition -> character device interface ]------------- */ 12.130 + 12.131 +/* /dev/xen/blktap resides at device number major=10, minor=200 */ 12.132 +#define BLKTAP_MINOR 202 12.133 + 12.134 +/* size of the extra VMA area to map in attached pages. */ 12.135 +#define BLKTAP_VMA_PAGES BLKIF_RING_SIZE 12.136 + 12.137 +/* blktap IOCTLs: */ 12.138 +#define BLKTAP_IOCTL_KICK_FE 1 12.139 +#define BLKTAP_IOCTL_KICK_BE 2 12.140 +#define BLKTAP_IOCTL_SETMODE 3 12.141 + 12.142 +/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE) */ 12.143 +#define BLKTAP_MODE_PASSTHROUGH 0x00000000 /* default */ 12.144 +#define BLKTAP_MODE_INTERCEPT_FE 0x00000001 12.145 +#define BLKTAP_MODE_INTERCEPT_BE 0x00000002 12.146 +#define BLKTAP_MODE_COPY_FE 0x00000004 12.147 +#define BLKTAP_MODE_COPY_BE 0x00000008 12.148 +#define BLKTAP_MODE_COPY_FE_PAGES 0x00000010 12.149 +#define BLKTAP_MODE_COPY_BE_PAGES 0x00000020 12.150 + 12.151 +#define BLKTAP_MODE_INTERPOSE \ 12.152 + (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE) 12.153 + 12.154 +#define BLKTAP_MODE_COPY_BOTH \ 12.155 + (BLKTAP_MODE_COPY_FE | BLKTAP_MODE_COPY_BE) 12.156 + 12.157 +#define BLKTAP_MODE_COPY_BOTH_PAGES \ 12.158 + (BLKTAP_MODE_COPY_FE_PAGES | BLKTAP_MODE_COPY_BE_PAGES) 12.159 + 12.160 +static inline int BLKTAP_MODE_VALID(unsigned long arg) 12.161 +{ 12.162 + return ( 12.163 + ( arg == BLKTAP_MODE_PASSTHROUGH ) || 12.164 + ( arg == BLKTAP_MODE_INTERCEPT_FE ) || 12.165 + ( arg == BLKTAP_MODE_INTERCEPT_BE ) || 12.166 + ( arg == BLKTAP_MODE_INTERPOSE ) || 12.167 + ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) || 12.168 + ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) || 12.169 + ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH ) 12.170 + ); 12.171 +} 12.172 + 12.173 + 12.174 + 12.175 +/* -------[ Mappings to User VMA ]------------------------------------ */ 12.176 +#define MAX_PENDING_REQS 64 12.177 +#define BATCH_PER_DOMAIN 16 12.178 +extern struct vm_area_struct *blktap_vma; 12.179 + 12.180 +/* The following are from blkback.c and should probably be put in a 12.181 + * header and included from there. 12.182 + * The mmap area described here is where attached data pages eill be mapped. 12.183 + */ 12.184 + 12.185 +extern unsigned long mmap_vstart; 12.186 +#define MMAP_PAGES_PER_REQUEST \ 12.187 + (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) 12.188 +#define MMAP_PAGES \ 12.189 + (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST) 12.190 +#define MMAP_VADDR(_req,_seg) \ 12.191 + (mmap_vstart + \ 12.192 + ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \ 12.193 + ((_seg) * PAGE_SIZE)) 12.194 + 12.195 +/* immediately before the mmap area, we have a bunch of pages reserved 12.196 + * for shared memory rings. 12.197 + */ 12.198 + 12.199 +#define RING_PAGES 128 12.200 +extern unsigned long rings_vstart; 12.201 + 12.202 +/* -------[ Here be globals ]----------------------------------------- */ 12.203 + 12.204 +extern unsigned long blktap_mode; 12.205 + 12.206 + 12.207 +/* blkif struct, containing ring to FE domain */ 12.208 +extern blkif_t ptfe_blkif; 12.209 + 12.210 +/* Connection to a single backend domain. */ 12.211 +extern blkif_ring_t *blk_ptbe_ring; /* Ring from the PT to the BE dom */ 12.212 +extern BLKIF_RING_IDX ptbe_resp_cons; /* Response consumer for comms ring. */ 12.213 +extern BLKIF_RING_IDX ptbe_req_prod; /* Private request producer. */ 12.214 + 12.215 +/* Rings up to user space. */ 12.216 +extern blkif_req_ring_t fe_ring;// = BLKIF_REQ_RING_INIT; 12.217 +extern blkif_rsp_ring_t be_ring;// = BLKIF_RSP_RING_INIT; 12.218 + 12.219 +/* Event channel to backend domain. */ 12.220 +extern unsigned int blkif_ptbe_evtchn; 12.221 + 12.222 +/* User ring status... this will soon vanish into a ring struct. */ 12.223 +extern unsigned long blktap_ring_ok; 12.224 + 12.225 +/* -------[ ...and function prototypes. ]----------------------------- */ 12.226 + 12.227 +/* init function for character device interface. */ 12.228 +int blktap_init(void); 12.229 + 12.230 +/* interfaces to the char driver, passing messages to and from apps. */ 12.231 +void blktap_kick_user(void); 12.232 +int blktap_write_to_ring(blkif_request_t *req); 12.233 + 12.234 + 12.235 +/* user ring access functions: */ 12.236 +int blktap_write_fe_ring(blkif_request_t *req); 12.237 +int blktap_write_be_ring(blkif_response_t *rsp); 12.238 +int blktap_read_fe_ring(void); 12.239 +int blktap_read_be_ring(void); 12.240 + 12.241 +/* and the helpers they call: */ 12.242 +inline int write_resp_to_fe_ring(blkif_response_t *rsp); 12.243 +inline void kick_fe_domain(void); 12.244 + 12.245 +inline int write_req_to_be_ring(blkif_request_t *req); 12.246 +inline void kick_be_domain(void); 12.247 + 12.248 +/* Interrupt handlers. */ 12.249 +irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 12.250 + struct pt_regs *ptregs); 12.251 +irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs); 12.252 + 12.253 +/* Control message receiver. */ 12.254 +extern void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id); 12.255 + 12.256 +#define __BLKINT_H__ 12.257 +#endif
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c Wed Nov 24 12:07:16 2004 +0000 13.3 @@ -0,0 +1,358 @@ 13.4 +/****************************************************************************** 13.5 + * blktap_controlmsg.c 13.6 + * 13.7 + * XenLinux virtual block-device tap. 13.8 + * Control interfaces to the frontend and backend drivers. 13.9 + * 13.10 + * Copyright (c) 2004, Andrew Warfield 13.11 + * 13.12 + */ 13.13 + 13.14 +#include "blktap.h" 13.15 + 13.16 +#define BLKIF_STATE_CLOSED 0 13.17 +#define BLKIF_STATE_DISCONNECTED 1 13.18 +#define BLKIF_STATE_CONNECTED 2 13.19 + 13.20 +static char *blkif_state_name[] = { 13.21 + [BLKIF_STATE_CLOSED] = "closed", 13.22 + [BLKIF_STATE_DISCONNECTED] = "disconnected", 13.23 + [BLKIF_STATE_CONNECTED] = "connected", 13.24 +}; 13.25 + 13.26 +static char * blkif_status_name[] = { 13.27 + [BLKIF_INTERFACE_STATUS_CLOSED] = "closed", 13.28 + [BLKIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected", 13.29 + [BLKIF_INTERFACE_STATUS_CONNECTED] = "connected", 13.30 + [BLKIF_INTERFACE_STATUS_CHANGED] = "changed", 13.31 +}; 13.32 +static unsigned int blkif_pt_state = BLKIF_STATE_CLOSED; 13.33 +static unsigned blkif_ptbe_irq; 13.34 +unsigned int blkif_ptbe_evtchn; 13.35 + 13.36 +/*-----[ Control Messages to/from Frontend VMs ]--------------------------*/ 13.37 + 13.38 + 13.39 +void blkif_ptfe_create(blkif_be_create_t *create) 13.40 +{ 13.41 + blkif_t *blkif; 13.42 + domid_t domid = create->domid; 13.43 + unsigned int handle = create->blkif_handle; 13.44 + 13.45 + 13.46 + /* May want to store info on the connecting domain here. */ 13.47 + 13.48 + DPRINTK("PT got BE_CREATE\n"); 13.49 + blkif = &ptfe_blkif; /* for convenience if the hash is readded later. */ 13.50 + 13.51 + /* blkif struct init code from blkback.c */ 13.52 + memset(blkif, 0, sizeof(*blkif)); 13.53 + blkif->domid = domid; 13.54 + blkif->handle = handle; 13.55 + blkif->status = DISCONNECTED; 13.56 + spin_lock_init(&blkif->blk_ring_lock); 13.57 + atomic_set(&blkif->refcnt, 0); 13.58 + 13.59 + create->status = BLKIF_BE_STATUS_OKAY; 13.60 +} 13.61 + 13.62 + 13.63 +void blkif_ptfe_destroy(blkif_be_destroy_t *destroy) 13.64 +{ 13.65 + /* Clear anything that we initialized above. */ 13.66 + 13.67 + DPRINTK("PT got BE_DESTROY\n"); 13.68 + destroy->status = BLKIF_BE_STATUS_OKAY; 13.69 +} 13.70 + 13.71 +void blkif_ptfe_connect(blkif_be_connect_t *connect) 13.72 +{ 13.73 + domid_t domid = connect->domid; 13.74 + /*unsigned int handle = connect->blkif_handle;*/ 13.75 + unsigned int evtchn = connect->evtchn; 13.76 + unsigned long shmem_frame = connect->shmem_frame; 13.77 + struct vm_struct *vma; 13.78 + pgprot_t prot; 13.79 + int error; 13.80 + blkif_t *blkif; 13.81 + 13.82 + DPRINTK("PT got BE_CONNECT\n"); 13.83 + 13.84 + blkif = &ptfe_blkif; /* for convenience if the hash is readded later. */ 13.85 + 13.86 + if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL ) 13.87 + { 13.88 + connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; 13.89 + return; 13.90 + } 13.91 + 13.92 + prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED); 13.93 + error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr), 13.94 + shmem_frame<<PAGE_SHIFT, PAGE_SIZE, 13.95 + prot, domid); 13.96 + if ( error != 0 ) 13.97 + { 13.98 + WPRINTK("BE_CONNECT: error! (%d)\n", error); 13.99 + if ( error == -ENOMEM ) 13.100 + connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; 13.101 + else if ( error == -EFAULT ) { 13.102 + connect->status = BLKIF_BE_STATUS_MAPPING_ERROR; 13.103 + WPRINTK("BE_CONNECT: MAPPING error!\n"); 13.104 + } 13.105 + else 13.106 + connect->status = BLKIF_BE_STATUS_ERROR; 13.107 + vfree(vma->addr); 13.108 + return; 13.109 + } 13.110 + 13.111 + if ( blkif->status != DISCONNECTED ) 13.112 + { 13.113 + connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED; 13.114 + vfree(vma->addr); 13.115 + return; 13.116 + } 13.117 + 13.118 + blkif->evtchn = evtchn; 13.119 + blkif->irq = bind_evtchn_to_irq(evtchn); 13.120 + blkif->shmem_frame = shmem_frame; 13.121 + blkif->blk_ring_base = (blkif_ring_t *)vma->addr; 13.122 + blkif->status = CONNECTED; 13.123 + /*blkif_get(blkif);*/ 13.124 + 13.125 + request_irq(blkif->irq, blkif_ptfe_int, 0, "blkif-pt-backend", blkif); 13.126 + 13.127 + connect->status = BLKIF_BE_STATUS_OKAY; 13.128 +} 13.129 + 13.130 +void blkif_ptfe_disconnect(blkif_be_disconnect_t *disconnect) 13.131 +{ 13.132 + /* 13.133 + * don't actually set the passthrough to disconnected. 13.134 + * We just act as a pipe, and defer to the real ends to handle things like 13.135 + * recovery. 13.136 + */ 13.137 + 13.138 + DPRINTK("PT got BE_DISCONNECT\n"); 13.139 + 13.140 + disconnect->status = BLKIF_BE_STATUS_OKAY; 13.141 + return; 13.142 +} 13.143 + 13.144 +/*-----[ Control Messages to/from Backend VM ]----------------------------*/ 13.145 + 13.146 +/* Tell the controller to bring up the interface. */ 13.147 +static void blkif_ptbe_send_interface_connect(void) 13.148 +{ 13.149 + ctrl_msg_t cmsg = { 13.150 + .type = CMSG_BLKIF_FE, 13.151 + .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT, 13.152 + .length = sizeof(blkif_fe_interface_connect_t), 13.153 + }; 13.154 + blkif_fe_interface_connect_t *msg = (void*)cmsg.msg; 13.155 + msg->handle = 0; 13.156 + msg->shmem_frame = virt_to_machine(blk_ptbe_ring) >> PAGE_SHIFT; 13.157 + 13.158 + ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); 13.159 +} 13.160 + 13.161 +static void blkif_ptbe_close(void) 13.162 +{ 13.163 +} 13.164 + 13.165 +/* Move from CLOSED to DISCONNECTED state. */ 13.166 +static void blkif_ptbe_disconnect(void) 13.167 +{ 13.168 + blk_ptbe_ring = (blkif_ring_t *)__get_free_page(GFP_KERNEL); 13.169 + blk_ptbe_ring->req_prod = blk_ptbe_ring->resp_prod 13.170 + = ptbe_resp_cons = ptbe_req_prod = 0; 13.171 + blkif_pt_state = BLKIF_STATE_DISCONNECTED; 13.172 + DPRINTK("Blkif-Passthrough-BE is now DISCONNECTED.\n"); 13.173 + blkif_ptbe_send_interface_connect(); 13.174 +} 13.175 + 13.176 +static void blkif_ptbe_connect(blkif_fe_interface_status_t *status) 13.177 +{ 13.178 + int err = 0; 13.179 + 13.180 + blkif_ptbe_evtchn = status->evtchn; 13.181 + blkif_ptbe_irq = bind_evtchn_to_irq(blkif_ptbe_evtchn); 13.182 + 13.183 + err = request_irq(blkif_ptbe_irq, blkif_ptbe_int, 13.184 + SA_SAMPLE_RANDOM, "blkif", NULL); 13.185 + if ( err ) { 13.186 + WPRINTK("blkfront request_irq failed (%d)\n", err); 13.187 + return; 13.188 + } else { 13.189 + /* transtion to connected in case we need to do a 13.190 + a partion probe on a whole disk */ 13.191 + blkif_pt_state = BLKIF_STATE_CONNECTED; 13.192 + } 13.193 +} 13.194 + 13.195 +static void unexpected(blkif_fe_interface_status_t *status) 13.196 +{ 13.197 + WPRINTK(" TAP: Unexpected blkif status %s in state %s\n", 13.198 + blkif_status_name[status->status], 13.199 + blkif_state_name[blkif_pt_state]); 13.200 +} 13.201 + 13.202 +static void blkif_ptbe_status( 13.203 + blkif_fe_interface_status_t *status) 13.204 +{ 13.205 + if ( status->handle != 0 ) 13.206 + { 13.207 + DPRINTK("Status change on unsupported blkif %d\n", 13.208 + status->handle); 13.209 + return; 13.210 + } 13.211 + 13.212 + DPRINTK("ptbe_status: got %s\n", blkif_status_name[status->status]); 13.213 + 13.214 + switch ( status->status ) 13.215 + { 13.216 + case BLKIF_INTERFACE_STATUS_CLOSED: 13.217 + switch ( blkif_pt_state ) 13.218 + { 13.219 + case BLKIF_STATE_CLOSED: 13.220 + unexpected(status); 13.221 + break; 13.222 + case BLKIF_STATE_DISCONNECTED: 13.223 + case BLKIF_STATE_CONNECTED: 13.224 + unexpected(status); 13.225 + blkif_ptbe_close(); 13.226 + break; 13.227 + } 13.228 + break; 13.229 + 13.230 + case BLKIF_INTERFACE_STATUS_DISCONNECTED: 13.231 + switch ( blkif_pt_state ) 13.232 + { 13.233 + case BLKIF_STATE_CLOSED: 13.234 + blkif_ptbe_disconnect(); 13.235 + break; 13.236 + case BLKIF_STATE_DISCONNECTED: 13.237 + case BLKIF_STATE_CONNECTED: 13.238 + printk(KERN_ALERT "*** add recovery code to the tap driver. ***\n"); 13.239 + unexpected(status); 13.240 + break; 13.241 + } 13.242 + break; 13.243 + 13.244 + case BLKIF_INTERFACE_STATUS_CONNECTED: 13.245 + switch ( blkif_pt_state ) 13.246 + { 13.247 + case BLKIF_STATE_CLOSED: 13.248 + unexpected(status); 13.249 + blkif_ptbe_disconnect(); 13.250 + blkif_ptbe_connect(status); 13.251 + break; 13.252 + case BLKIF_STATE_DISCONNECTED: 13.253 + blkif_ptbe_connect(status); 13.254 + break; 13.255 + case BLKIF_STATE_CONNECTED: 13.256 + unexpected(status); 13.257 + blkif_ptbe_connect(status); 13.258 + break; 13.259 + } 13.260 + break; 13.261 + 13.262 + case BLKIF_INTERFACE_STATUS_CHANGED: 13.263 + switch ( blkif_pt_state ) 13.264 + { 13.265 + case BLKIF_STATE_CLOSED: 13.266 + case BLKIF_STATE_DISCONNECTED: 13.267 + unexpected(status); 13.268 + break; 13.269 + case BLKIF_STATE_CONNECTED: 13.270 + /* vbd_update(); */ 13.271 + /* tap doesn't really get state changes... */ 13.272 + unexpected(status); 13.273 + break; 13.274 + } 13.275 + break; 13.276 + 13.277 + default: 13.278 + DPRINTK("Status change to unknown value %d\n", status->status); 13.279 + break; 13.280 + } 13.281 +} 13.282 + 13.283 +/*-----[ All control messages enter here: ]-------------------------------*/ 13.284 + 13.285 +void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) 13.286 +{ 13.287 + switch ( msg->type ) 13.288 + { 13.289 + case CMSG_BLKIF_FE: 13.290 + 13.291 + switch ( msg->subtype ) 13.292 + { 13.293 + case CMSG_BLKIF_FE_INTERFACE_STATUS: 13.294 + if ( msg->length != sizeof(blkif_fe_interface_status_t) ) 13.295 + goto parse_error; 13.296 + blkif_ptbe_status((blkif_fe_interface_status_t *) &msg->msg[0]); 13.297 + break; 13.298 + 13.299 + default: 13.300 + goto parse_error; 13.301 + } 13.302 + 13.303 + case CMSG_BLKIF_BE: 13.304 + 13.305 + switch ( msg->subtype ) 13.306 + { 13.307 + case CMSG_BLKIF_BE_CREATE: 13.308 + if ( msg->length != sizeof(blkif_be_create_t) ) 13.309 + goto parse_error; 13.310 + blkif_ptfe_create((blkif_be_create_t *)&msg->msg[0]); 13.311 + break; 13.312 + case CMSG_BLKIF_BE_DESTROY: 13.313 + if ( msg->length != sizeof(blkif_be_destroy_t) ) 13.314 + goto parse_error; 13.315 + blkif_ptfe_destroy((blkif_be_destroy_t *)&msg->msg[0]); 13.316 + break; 13.317 + case CMSG_BLKIF_BE_CONNECT: 13.318 + if ( msg->length != sizeof(blkif_be_connect_t) ) 13.319 + goto parse_error; 13.320 + blkif_ptfe_connect((blkif_be_connect_t *)&msg->msg[0]); 13.321 + break; 13.322 + case CMSG_BLKIF_BE_DISCONNECT: 13.323 + if ( msg->length != sizeof(blkif_be_disconnect_t) ) 13.324 + goto parse_error; 13.325 + blkif_ptfe_disconnect((blkif_be_disconnect_t *)&msg->msg[0]); 13.326 + break; 13.327 + 13.328 + /* We just ignore anything to do with vbds for now. */ 13.329 + 13.330 + case CMSG_BLKIF_BE_VBD_CREATE: 13.331 + DPRINTK("PT got VBD_CREATE\n"); 13.332 + ((blkif_be_vbd_create_t *)&msg->msg[0])->status 13.333 + = BLKIF_BE_STATUS_OKAY; 13.334 + break; 13.335 + case CMSG_BLKIF_BE_VBD_DESTROY: 13.336 + DPRINTK("PT got VBD_DESTROY\n"); 13.337 + ((blkif_be_vbd_destroy_t *)&msg->msg[0])->status 13.338 + = BLKIF_BE_STATUS_OKAY; 13.339 + break; 13.340 + case CMSG_BLKIF_BE_VBD_GROW: 13.341 + DPRINTK("PT got VBD_GROW\n"); 13.342 + ((blkif_be_vbd_grow_t *)&msg->msg[0])->status 13.343 + = BLKIF_BE_STATUS_OKAY; 13.344 + break; 13.345 + case CMSG_BLKIF_BE_VBD_SHRINK: 13.346 + DPRINTK("PT got VBD_SHRINK\n"); 13.347 + ((blkif_be_vbd_shrink_t *)&msg->msg[0])->status 13.348 + = BLKIF_BE_STATUS_OKAY; 13.349 + break; 13.350 + default: 13.351 + goto parse_error; 13.352 + } 13.353 + } 13.354 + 13.355 + ctrl_if_send_response(msg); 13.356 + return; 13.357 + 13.358 + parse_error: 13.359 + msg->length = 0; 13.360 + ctrl_if_send_response(msg); 13.361 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_datapath.c Wed Nov 24 12:07:16 2004 +0000 14.3 @@ -0,0 +1,517 @@ 14.4 +/****************************************************************************** 14.5 + * blktap_datapath.c 14.6 + * 14.7 + * XenLinux virtual block-device tap. 14.8 + * Block request routing data path. 14.9 + * 14.10 + * Copyright (c) 2004, Andrew Warfield 14.11 + * 14.12 + */ 14.13 + 14.14 +#include "blktap.h" 14.15 + 14.16 +/*-----[ The data paths ]-------------------------------------------------*/ 14.17 + 14.18 +/* Connections to the frontend domains.*/ 14.19 +blkif_t ptfe_blkif; 14.20 + 14.21 +/* Connection to a single backend domain. */ 14.22 +blkif_ring_t *blk_ptbe_ring; /* Ring from the PT to the BE dom */ 14.23 +BLKIF_RING_IDX ptbe_resp_cons; /* Response consumer for comms ring. */ 14.24 +BLKIF_RING_IDX ptbe_req_prod; /* Private request producer. */ 14.25 + 14.26 +/* Rings up to user space. */ 14.27 +blkif_req_ring_t fe_ring;// = BLKIF_REQ_RING_INIT; 14.28 +blkif_rsp_ring_t be_ring;// = BLKIF_RSP_RING_INIT; 14.29 + 14.30 +/*-----[ Ring helpers ]---------------------------------------------------*/ 14.31 + 14.32 +inline int BLKTAP_RING_FULL(blkif_generic_ring_t *ring) 14.33 +{ 14.34 + if (ring->type == BLKIF_REQ_RING_TYPE) { 14.35 + blkif_req_ring_t *r = (blkif_req_ring_t *)ring; 14.36 + return ( ( r->req_prod - r->rsp_cons ) == BLKIF_RING_SIZE ); 14.37 + } 14.38 + 14.39 + /* for now assume that there is always room in the response path. */ 14.40 + return 0; 14.41 +} 14.42 + 14.43 +/*-----[ Tracking active requests ]---------------------------------------*/ 14.44 + 14.45 +/* this must be the same as MAX_PENDING_REQS in blkback.c */ 14.46 +#define MAX_ACTIVE_REQS 64 14.47 + 14.48 +active_req_t active_reqs[MAX_ACTIVE_REQS]; 14.49 +unsigned char active_req_ring[MAX_ACTIVE_REQS]; 14.50 +spinlock_t active_req_lock = SPIN_LOCK_UNLOCKED; 14.51 +typedef unsigned int ACTIVE_RING_IDX; 14.52 +ACTIVE_RING_IDX active_prod, active_cons; 14.53 +#define MASK_ACTIVE_IDX(_i) ((_i)&(MAX_ACTIVE_REQS-1)) 14.54 +#define ACTIVE_IDX(_ar) (_ar - active_reqs) 14.55 + 14.56 +inline active_req_t *get_active_req(void) 14.57 +{ 14.58 + ASSERT(active_cons != active_prod); 14.59 + return &active_reqs[MASK_ACTIVE_IDX(active_cons++)]; 14.60 +} 14.61 + 14.62 +inline void free_active_req(active_req_t *ar) 14.63 +{ 14.64 + unsigned long flags; 14.65 + 14.66 + spin_lock_irqsave(&active_req_lock, flags); 14.67 + active_req_ring[MASK_ACTIVE_IDX(active_prod++)] = ACTIVE_IDX(ar); 14.68 + spin_unlock_irqrestore(&active_req_lock, flags); 14.69 +} 14.70 + 14.71 +inline void active_reqs_init(void) 14.72 +{ 14.73 + ACTIVE_RING_IDX i; 14.74 + 14.75 + active_cons = 0; 14.76 + active_prod = MAX_ACTIVE_REQS; 14.77 + memset(active_reqs, 0, sizeof(active_reqs)); 14.78 + for ( i = 0; i < MAX_ACTIVE_REQS; i++ ) 14.79 + active_req_ring[i] = i; 14.80 +} 14.81 + 14.82 +/*-----[ Data to/from Frontend (client) VMs ]-----------------------------*/ 14.83 + 14.84 +irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs) 14.85 +{ 14.86 + /* we have pending messages from the real frontend. */ 14.87 + 14.88 + blkif_request_t *req_s, *req_d; 14.89 + BLKIF_RING_IDX fe_rp; 14.90 + unsigned long flags; 14.91 + int notify; 14.92 + unsigned long i; 14.93 + active_req_t *ar; 14.94 + 14.95 + DPRINTK("PT got FE interrupt.\n"); 14.96 + 14.97 + /* lock both rings */ 14.98 + spin_lock_irqsave(&blkif_io_lock, flags); 14.99 + 14.100 + /* While there are REQUESTS on FERing: */ 14.101 + fe_rp = ptfe_blkif.blk_ring_base->req_prod; 14.102 + rmb(); 14.103 + notify = (ptfe_blkif.blk_req_cons != fe_rp); 14.104 + 14.105 + for (i = ptfe_blkif.blk_req_cons; i != fe_rp; i++) { 14.106 + 14.107 + /* Get the next request */ 14.108 + req_s = &ptfe_blkif.blk_ring_base->ring[MASK_BLKIF_IDX(i)].req; 14.109 + 14.110 + /* This is a new request: 14.111 + * Assign an active request record, and remap the id. 14.112 + */ 14.113 + ar = get_active_req(); 14.114 + ar->id = req_s->id; 14.115 + req_s->id = ACTIVE_IDX(ar); 14.116 + DPRINTK("%3lu < %3lu\n", req_s->id, ar->id); 14.117 + 14.118 + /* FE -> BE interposition point is here. */ 14.119 + 14.120 + /* ------------------------------------------------------------- */ 14.121 + /* BLKIF_OP_PROBE_HACK: */ 14.122 + /* Until we have grant tables, we need to allow the backent to */ 14.123 + /* map pages that are either from this domain, or more commonly */ 14.124 + /* from the real front end. We achieve this in a terrible way, */ 14.125 + /* by passing the front end's domid allong with PROBE messages */ 14.126 + /* Once grant tables appear, this should all go away. */ 14.127 + 14.128 + if (req_s->operation == BLKIF_OP_PROBE) { 14.129 + DPRINTK("Adding FE domid to PROBE request.\n"); 14.130 + (domid_t)(req_s->frame_and_sects[1]) = ptfe_blkif.domid; 14.131 + } 14.132 + 14.133 + /* ------------------------------------------------------------- */ 14.134 + 14.135 + /* If we are in MODE_INTERCEPT_FE or MODE_COPY_FE: */ 14.136 + if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) || 14.137 + (blktap_mode & BLKTAP_MODE_COPY_FE) ) { 14.138 + 14.139 + /* Copy the response message to UFERing */ 14.140 + /* In MODE_INTERCEPT_FE, map attached pages into the app vma */ 14.141 + /* In MODE_COPY_FE_PAGES, copy attached pages into the app vma */ 14.142 + 14.143 + /* XXX: mapping/copying of attached pages is still not done! */ 14.144 + 14.145 + DPRINTK("req->UFERing\n"); 14.146 + blktap_write_fe_ring(req_s); 14.147 + 14.148 + 14.149 + } 14.150 + 14.151 + /* If we are not in MODE_INTERCEPT_FE or MODE_INTERCEPT_BE: */ 14.152 + if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) || 14.153 + (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) { 14.154 + 14.155 + /* be included to prevent noise from the fe when its off */ 14.156 + /* copy the request message to the BERing */ 14.157 + 14.158 + DPRINTK("blktap: FERing[%u] -> BERing[%u]\n", 14.159 + (unsigned)MASK_BLKIF_IDX(i), 14.160 + (unsigned)MASK_BLKIF_IDX(ptbe_req_prod)); 14.161 + 14.162 + req_d = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(ptbe_req_prod)].req; 14.163 + 14.164 + memcpy(req_d, req_s, sizeof(blkif_request_t)); 14.165 + 14.166 + ptbe_req_prod++; 14.167 + } 14.168 + } 14.169 + 14.170 + ptfe_blkif.blk_req_cons = i; 14.171 + 14.172 + /* If we have forwarded any responses, notify the appropriate ends. */ 14.173 + if (notify) { 14.174 + 14.175 + /* we have sent stuff to the be, notify it. */ 14.176 + if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) || 14.177 + (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) { 14.178 + wmb(); 14.179 + blk_ptbe_ring->req_prod = ptbe_req_prod; 14.180 + 14.181 + notify_via_evtchn(blkif_ptbe_evtchn); 14.182 + DPRINTK(" -- and notified.\n"); 14.183 + } 14.184 + 14.185 + /* we sent stuff to the app, notify it. */ 14.186 + if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) || 14.187 + (blktap_mode & BLKTAP_MODE_COPY_FE) ) { 14.188 + 14.189 + blktap_kick_user(); 14.190 + } 14.191 + } 14.192 + 14.193 + /* unlock rings */ 14.194 + spin_unlock_irqrestore(&blkif_io_lock, flags); 14.195 + 14.196 + return IRQ_HANDLED; 14.197 +} 14.198 + 14.199 +inline int write_req_to_be_ring(blkif_request_t *req) 14.200 +{ 14.201 + blkif_request_t *req_d; 14.202 + 14.203 + req_d = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(ptbe_req_prod)].req; 14.204 + memcpy(req_d, req, sizeof(blkif_request_t)); 14.205 + ptbe_req_prod++; 14.206 + 14.207 + return 0; 14.208 +} 14.209 + 14.210 +inline void kick_be_domain(void) { 14.211 + wmb(); 14.212 + blk_ptbe_ring->req_prod = ptbe_req_prod; 14.213 + notify_via_evtchn(blkif_ptbe_evtchn); 14.214 +} 14.215 + 14.216 +/*-----[ Data to/from Backend (server) VM ]------------------------------*/ 14.217 + 14.218 + 14.219 +irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 14.220 + struct pt_regs *ptregs) 14.221 +{ 14.222 + blkif_response_t *resp_s, *resp_d; 14.223 + BLKIF_RING_IDX be_rp; 14.224 + unsigned long flags; 14.225 + int notify; 14.226 + unsigned long i; 14.227 + active_req_t *ar; 14.228 + 14.229 + DPRINTK("PT got BE interrupt.\n"); 14.230 + 14.231 + /* lock both rings */ 14.232 + spin_lock_irqsave(&blkif_io_lock, flags); 14.233 + 14.234 + /* While there are RESPONSES on BERing: */ 14.235 + be_rp = blk_ptbe_ring->resp_prod; 14.236 + rmb(); 14.237 + notify = (ptbe_resp_cons != be_rp); 14.238 + 14.239 + for ( i = ptbe_resp_cons; i != be_rp; i++ ) 14.240 + { 14.241 + /* BE -> FE interposition point is here. */ 14.242 + 14.243 + /* Get the next response */ 14.244 + resp_s = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(i)].resp; 14.245 + 14.246 + 14.247 + /* If we are in MODE_INTERCEPT_BE or MODE_COPY_BE: */ 14.248 + if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) || 14.249 + (blktap_mode & BLKTAP_MODE_COPY_BE) ) { 14.250 + 14.251 + /* Copy the response message to UBERing */ 14.252 + /* In MODE_INTERCEPT_BE, map attached pages into the app vma */ 14.253 + /* In MODE_COPY_BE_PAGES, copy attached pages into the app vma */ 14.254 + 14.255 + /* XXX: copy/map the attached page! */ 14.256 + 14.257 + DPRINTK("rsp->UBERing\n"); 14.258 + blktap_write_be_ring(resp_s); 14.259 + 14.260 + } 14.261 + 14.262 + /* If we are NOT in MODE_INTERCEPT_BE or MODE_INTERCEPT_FE: */ 14.263 + if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) || 14.264 + (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) { 14.265 + 14.266 + /* (fe included to prevent random interference from the BE) */ 14.267 + /* Copy the response message to FERing */ 14.268 + 14.269 + DPRINTK("blktap: BERing[%u] -> FERing[%u]\n", 14.270 + (unsigned) MASK_BLKIF_IDX(i), 14.271 + (unsigned) MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod)); 14.272 + 14.273 + /* remap id, and free the active req. blkif lookup goes here too.*/ 14.274 + ar = &active_reqs[resp_s->id]; 14.275 + DPRINTK("%3lu > %3lu\n", resp_s->id, ar->id); 14.276 + resp_s->id = ar->id; 14.277 + free_active_req(ar); 14.278 + 14.279 + resp_d = &ptfe_blkif.blk_ring_base->ring[ 14.280 + MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod)].resp; 14.281 + 14.282 + memcpy(resp_d, resp_s, sizeof(blkif_response_t)); 14.283 + 14.284 + ptfe_blkif.blk_resp_prod++; 14.285 + 14.286 + } 14.287 + } 14.288 + 14.289 + ptbe_resp_cons = i; 14.290 + 14.291 + /* If we have forwarded any responses, notify the apropriate domains. */ 14.292 + if (notify) { 14.293 + 14.294 + /* we have sent stuff to the fe. notify it. */ 14.295 + if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) || 14.296 + (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) { 14.297 + wmb(); 14.298 + ptfe_blkif.blk_ring_base->resp_prod = ptfe_blkif.blk_resp_prod; 14.299 + 14.300 + notify_via_evtchn(ptfe_blkif.evtchn); 14.301 + DPRINTK(" -- and notified.\n"); 14.302 + } 14.303 + 14.304 + /* we sent stuff to the app, notify it. */ 14.305 + if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) || 14.306 + (blktap_mode & BLKTAP_MODE_COPY_BE) ) { 14.307 + 14.308 + blktap_kick_user(); 14.309 + } 14.310 + } 14.311 + 14.312 + spin_unlock_irqrestore(&blkif_io_lock, flags); 14.313 + return IRQ_HANDLED; 14.314 +} 14.315 + 14.316 +inline int write_resp_to_fe_ring(blkif_response_t *rsp) 14.317 +{ 14.318 + blkif_response_t *resp_d; 14.319 + active_req_t *ar; 14.320 + 14.321 + /* remap id, and free the active req. blkif lookup goes here too.*/ 14.322 + ar = &active_reqs[rsp->id]; 14.323 + DPRINTK("%3lu > %3lu\n", rsp->id, ar->id); 14.324 + rsp->id = ar->id; 14.325 + free_active_req(ar); 14.326 + 14.327 + resp_d = &ptfe_blkif.blk_ring_base->ring[ 14.328 + MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod)].resp; 14.329 + 14.330 + memcpy(resp_d, rsp, sizeof(blkif_response_t)); 14.331 + ptfe_blkif.blk_resp_prod++; 14.332 + 14.333 + return 0; 14.334 +} 14.335 + 14.336 +inline void kick_fe_domain(void) { 14.337 + wmb(); 14.338 + ptfe_blkif.blk_ring_base->resp_prod = ptfe_blkif.blk_resp_prod; 14.339 + notify_via_evtchn(ptfe_blkif.evtchn); 14.340 + 14.341 +} 14.342 + 14.343 +static inline void flush_requests(void) 14.344 +{ 14.345 + wmb(); /* Ensure that the frontend can see the requests. */ 14.346 + blk_ptbe_ring->req_prod = ptbe_req_prod; 14.347 + notify_via_evtchn(blkif_ptbe_evtchn); 14.348 +} 14.349 + 14.350 +/*-----[ Data to/from user space ]----------------------------------------*/ 14.351 + 14.352 + 14.353 +int blktap_write_fe_ring(blkif_request_t *req) 14.354 +{ 14.355 + blkif_request_t *target; 14.356 + int error, i; 14.357 + 14.358 + /* 14.359 + * This is called to pass a request from the real frontend domain's 14.360 + * blkif ring to the character device. 14.361 + */ 14.362 + 14.363 + if ( ! blktap_ring_ok ) { 14.364 + DPRINTK("blktap: fe_ring not ready for a request!\n"); 14.365 + return 0; 14.366 + } 14.367 + 14.368 + if ( BLKTAP_RING_FULL(RING(&fe_ring)) ) { 14.369 + DPRINTK("blktap: fe_ring is full, can't add.\n"); 14.370 + return 0; 14.371 + } 14.372 + 14.373 + target = &fe_ring.ring->ring[MASK_BLKIF_IDX(fe_ring.req_prod)].req; 14.374 + memcpy(target, req, sizeof(*req)); 14.375 + 14.376 +/* maybe move this stuff out into a seperate func ------------------- */ 14.377 + 14.378 + /* 14.379 + * For now, map attached page into a fixed position into the vma. 14.380 + * XXX: make this map to a free page. 14.381 + */ 14.382 + 14.383 + /* Attempt to map the foreign pages directly in to the application */ 14.384 + for (i=0; i<target->nr_segments; i++) { 14.385 + 14.386 + /* get an unused virtual address from the char device */ 14.387 + /* store the old page address */ 14.388 + /* replace the address with the virtual address */ 14.389 + 14.390 + /* blktap_vma->vm_start+((2+i)*PAGE_SIZE) */ 14.391 + 14.392 + error = direct_remap_area_pages(blktap_vma->vm_mm, 14.393 + MMAP_VADDR(req->id, i), 14.394 + target->frame_and_sects[0] & PAGE_MASK, 14.395 + PAGE_SIZE, 14.396 + blktap_vma->vm_page_prot, 14.397 + ptfe_blkif.domid); 14.398 + if ( error != 0 ) { 14.399 + printk(KERN_INFO "remapping attached page failed! (%d)\n", error); 14.400 + return 0; 14.401 + } 14.402 + } 14.403 + /* fix the address of the attached page in the message. */ 14.404 + /* TODO: preserve the segment number stuff here... */ 14.405 + /* target->frame_and_sects[0] = blktap_vma->vm_start + PAGE_SIZE;*/ 14.406 +/* ------------------------------------------------------------------ */ 14.407 + 14.408 + 14.409 + fe_ring.req_prod++; 14.410 + 14.411 + return 0; 14.412 +} 14.413 + 14.414 +int blktap_write_be_ring(blkif_response_t *rsp) 14.415 +{ 14.416 + blkif_response_t *target; 14.417 + 14.418 + /* 14.419 + * This is called to pass a request from the real backend domain's 14.420 + * blkif ring to the character device. 14.421 + */ 14.422 + 14.423 + if ( ! blktap_ring_ok ) { 14.424 + DPRINTK("blktap: be_ring not ready for a request!\n"); 14.425 + return 0; 14.426 + } 14.427 + 14.428 + if ( BLKTAP_RING_FULL(RING(&be_ring)) ) { 14.429 + DPRINTK("blktap: be_ring is full, can't add.\n"); 14.430 + return 0; 14.431 + } 14.432 + 14.433 + target = &be_ring.ring->ring[MASK_BLKIF_IDX(be_ring.rsp_prod)].resp; 14.434 + memcpy(target, rsp, sizeof(*rsp)); 14.435 + 14.436 + 14.437 + /* XXX: map attached pages and fix-up addresses in the copied address. */ 14.438 + 14.439 + be_ring.rsp_prod++; 14.440 + 14.441 + return 0; 14.442 +} 14.443 + 14.444 +int blktap_read_fe_ring(void) 14.445 +{ 14.446 + /* This is called to read responses from the UFE ring. */ 14.447 + 14.448 + BLKIF_RING_IDX fe_rp; 14.449 + unsigned long i; 14.450 + int notify; 14.451 + 14.452 + DPRINTK("blktap_read_fe_ring()\n"); 14.453 + 14.454 + fe_rp = fe_ring.ring->resp_prod; 14.455 + rmb(); 14.456 + notify = (fe_rp != fe_ring.rsp_cons); 14.457 + 14.458 + /* if we are forwarding from UFERring to FERing */ 14.459 + if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) { 14.460 + 14.461 + /* for each outstanding message on the UFEring */ 14.462 + for ( i = fe_ring.rsp_cons; i != fe_rp; i++ ) { 14.463 + 14.464 + /* XXX: remap pages on that message as necessary */ 14.465 + /* copy the message to the UBEring */ 14.466 + 14.467 + DPRINTK("resp->fe_ring\n"); 14.468 + write_resp_to_fe_ring(&fe_ring.ring->ring[MASK_BLKIF_IDX(i)].resp); 14.469 + } 14.470 + 14.471 + fe_ring.rsp_cons = fe_rp; 14.472 + 14.473 + /* notify the fe if necessary */ 14.474 + if ( notify ) { 14.475 + DPRINTK("kick_fe_domain()\n"); 14.476 + kick_fe_domain(); 14.477 + } 14.478 + } 14.479 + 14.480 + return 0; 14.481 +} 14.482 + 14.483 +int blktap_read_be_ring(void) 14.484 +{ 14.485 + /* This is called to read responses from the UBE ring. */ 14.486 + 14.487 + BLKIF_RING_IDX be_rp; 14.488 + unsigned long i; 14.489 + int notify; 14.490 + 14.491 + DPRINTK("blktap_read_be_ring()\n"); 14.492 + 14.493 + be_rp = be_ring.ring->req_prod; 14.494 + rmb(); 14.495 + notify = (be_rp != be_ring.req_cons); 14.496 + 14.497 + /* if we are forwarding from UFERring to FERing */ 14.498 + if (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) { 14.499 + 14.500 + /* for each outstanding message on the UFEring */ 14.501 + for ( i = be_ring.req_cons; i != be_rp; i++ ) { 14.502 + 14.503 + /* XXX: remap pages on that message as necessary */ 14.504 + /* copy the message to the UBEring */ 14.505 + 14.506 + DPRINTK("req->be_ring\n"); 14.507 + write_req_to_be_ring(&be_ring.ring->ring[MASK_BLKIF_IDX(i)].req); 14.508 + } 14.509 + 14.510 + be_ring.req_cons = be_rp; 14.511 + 14.512 + /* notify the fe if necessary */ 14.513 + if ( notify ) { 14.514 + DPRINTK("kick_be_domain()\n"); 14.515 + kick_be_domain(); 14.516 + } 14.517 + } 14.518 + 14.519 + return 0; 14.520 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_userdev.c Wed Nov 24 12:07:16 2004 +0000 15.3 @@ -0,0 +1,243 @@ 15.4 +/****************************************************************************** 15.5 + * blktap_userdev.c 15.6 + * 15.7 + * XenLinux virtual block-device tap. 15.8 + * Control interface between the driver and a character device. 15.9 + * 15.10 + * Copyright (c) 2004, Andrew Warfield 15.11 + * 15.12 + */ 15.13 + 15.14 +#include <linux/config.h> 15.15 +#include <linux/module.h> 15.16 +#include <linux/kernel.h> 15.17 +#include <linux/fs.h> 15.18 +#include <linux/mm.h> 15.19 +#include <linux/miscdevice.h> 15.20 +#include <linux/errno.h> 15.21 +#include <linux/major.h> 15.22 +#include <linux/gfp.h> 15.23 +#include <linux/poll.h> 15.24 +#include <asm/pgalloc.h> 15.25 + 15.26 +#include "blktap.h" 15.27 + 15.28 + 15.29 +unsigned long blktap_mode = BLKTAP_MODE_PASSTHROUGH; 15.30 + 15.31 +/* Only one process may open /dev/xen/blktap at any time. */ 15.32 +static unsigned long blktap_dev_inuse; 15.33 +unsigned long blktap_ring_ok; /* make this ring->state */ 15.34 + 15.35 +/* for poll: */ 15.36 +static wait_queue_head_t blktap_wait; 15.37 + 15.38 +/* Where things are inside the device mapping. */ 15.39 +struct vm_area_struct *blktap_vma; 15.40 +unsigned long mmap_vstart; 15.41 +unsigned long rings_vstart; 15.42 + 15.43 +/* -------[ blktap vm ops ]------------------------------------------- */ 15.44 + 15.45 +static struct page *blktap_nopage(struct vm_area_struct *vma, 15.46 + unsigned long address, 15.47 + int *type) 15.48 +{ 15.49 + /* 15.50 + * if the page has not been mapped in by the driver then generate 15.51 + * a SIGBUS to the domain. 15.52 + */ 15.53 + 15.54 + force_sig(SIGBUS, current); 15.55 + 15.56 + return 0; 15.57 +} 15.58 + 15.59 +struct vm_operations_struct blktap_vm_ops = { 15.60 + nopage: blktap_nopage, 15.61 +}; 15.62 + 15.63 +/* -------[ blktap file ops ]----------------------------------------- */ 15.64 + 15.65 +static int blktap_open(struct inode *inode, struct file *filp) 15.66 +{ 15.67 + if ( test_and_set_bit(0, &blktap_dev_inuse) ) 15.68 + return -EBUSY; 15.69 + 15.70 + printk(KERN_ALERT "blktap open.\n"); 15.71 + 15.72 + /* Allocate the fe ring. */ 15.73 + fe_ring.ring = (blkif_ring_t *)get_zeroed_page(GFP_KERNEL); 15.74 + if (fe_ring.ring == NULL) 15.75 + goto fail_nomem; 15.76 + 15.77 + SetPageReserved(virt_to_page(fe_ring.ring)); 15.78 + 15.79 + fe_ring.ring->req_prod = fe_ring.ring->resp_prod 15.80 + = fe_ring.req_prod 15.81 + = fe_ring.rsp_cons 15.82 + = 0; 15.83 + 15.84 + /* Allocate the be ring. */ 15.85 + be_ring.ring = (blkif_ring_t *)get_zeroed_page(GFP_KERNEL); 15.86 + if (be_ring.ring == NULL) 15.87 + goto fail_free_fe; 15.88 + 15.89 + SetPageReserved(virt_to_page(be_ring.ring)); 15.90 + 15.91 + be_ring.ring->req_prod = be_ring.ring->resp_prod 15.92 + = be_ring.rsp_prod 15.93 + = be_ring.req_cons 15.94 + = 0; 15.95 + 15.96 + DPRINTK(KERN_ALERT "blktap open.\n"); 15.97 + 15.98 + return 0; 15.99 + 15.100 + fail_free_fe: 15.101 + free_page( (unsigned long) fe_ring.ring); 15.102 + 15.103 + fail_nomem: 15.104 + return -ENOMEM; 15.105 +} 15.106 + 15.107 +static int blktap_release(struct inode *inode, struct file *filp) 15.108 +{ 15.109 + blktap_dev_inuse = 0; 15.110 + blktap_ring_ok = 0; 15.111 + 15.112 + printk(KERN_ALERT "blktap closed.\n"); 15.113 + 15.114 + /* Free the ring page. */ 15.115 + ClearPageReserved(virt_to_page(fe_ring.ring)); 15.116 + free_page((unsigned long) fe_ring.ring); 15.117 + 15.118 + ClearPageReserved(virt_to_page(be_ring.ring)); 15.119 + free_page((unsigned long) be_ring.ring); 15.120 + 15.121 + return 0; 15.122 +} 15.123 + 15.124 +static int blktap_mmap(struct file *filp, struct vm_area_struct *vma) 15.125 +{ 15.126 + int size; 15.127 + 15.128 + printk(KERN_ALERT "blktap mmap (%lx, %lx)\n", 15.129 + vma->vm_start, vma->vm_end); 15.130 + 15.131 + vma->vm_ops = &blktap_vm_ops; 15.132 + 15.133 + size = vma->vm_end - vma->vm_start; 15.134 + if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) { 15.135 + printk(KERN_INFO 15.136 + "blktap: you _must_ map exactly %d pages!\n", 15.137 + MMAP_PAGES + RING_PAGES); 15.138 + return -EAGAIN; 15.139 + } 15.140 + 15.141 + size >>= PAGE_SHIFT; 15.142 + printk(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1); 15.143 + 15.144 + rings_vstart = vma->vm_start; 15.145 + mmap_vstart = rings_vstart + (RING_PAGES << PAGE_SHIFT); 15.146 + 15.147 + /* Map the ring pages to the start of the region and reserve it. */ 15.148 + 15.149 + /* not sure if I really need to do this... */ 15.150 + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 15.151 + 15.152 + DPRINTK("Mapping be_ring page %lx.\n", __pa(be_ring.ring)); 15.153 + if (remap_page_range(vma, vma->vm_start, __pa(be_ring.ring), PAGE_SIZE, 15.154 + vma->vm_page_prot)) { 15.155 + printk(KERN_ERR "be_ring: remap_page_range failure!\n"); 15.156 + } 15.157 + 15.158 + DPRINTK("Mapping fe_ring page %lx.\n", __pa(fe_ring.ring)); 15.159 + if (remap_page_range(vma, vma->vm_start + PAGE_SIZE, __pa(fe_ring.ring), 15.160 + PAGE_SIZE, vma->vm_page_prot)) { 15.161 + printk(KERN_ERR "fe_ring: remap_page_range failure!\n"); 15.162 + } 15.163 + 15.164 + blktap_vma = vma; 15.165 + blktap_ring_ok = 1; 15.166 + 15.167 + return 0; 15.168 +} 15.169 + 15.170 +static int blktap_ioctl(struct inode *inode, struct file *filp, 15.171 + unsigned int cmd, unsigned long arg) 15.172 +{ 15.173 + switch(cmd) { 15.174 + case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */ 15.175 + return blktap_read_fe_ring(); 15.176 + 15.177 + case BLKTAP_IOCTL_KICK_BE: /* There are be messages to process. */ 15.178 + return blktap_read_be_ring(); 15.179 + 15.180 + case BLKTAP_IOCTL_SETMODE: 15.181 + if (BLKTAP_MODE_VALID(arg)) { 15.182 + blktap_mode = arg; 15.183 + /* XXX: may need to flush rings here. */ 15.184 + printk(KERN_INFO "blktap: set mode to %lx\n", arg); 15.185 + return 0; 15.186 + } 15.187 + /* XXX: return a more meaningful error case here. */ 15.188 + } 15.189 + return -ENOIOCTLCMD; 15.190 +} 15.191 + 15.192 +static unsigned int blktap_poll(struct file *file, poll_table *wait) 15.193 +{ 15.194 + poll_wait(file, &blktap_wait, wait); 15.195 + 15.196 + if ( (fe_ring.req_prod != fe_ring.ring->req_prod) || 15.197 + (be_ring.rsp_prod != be_ring.ring->resp_prod) ) { 15.198 + 15.199 + fe_ring.ring->req_prod = fe_ring.req_prod; 15.200 + be_ring.ring->resp_prod = be_ring.rsp_prod; 15.201 + return POLLIN | POLLRDNORM; 15.202 + } 15.203 + 15.204 + return 0; 15.205 +} 15.206 + 15.207 +void blktap_kick_user(void) 15.208 +{ 15.209 + /* blktap_ring->req_prod = blktap_req_prod; */ 15.210 + wake_up_interruptible(&blktap_wait); 15.211 +} 15.212 + 15.213 +static struct file_operations blktap_fops = { 15.214 + owner: THIS_MODULE, 15.215 + poll: blktap_poll, 15.216 + ioctl: blktap_ioctl, 15.217 + open: blktap_open, 15.218 + release: blktap_release, 15.219 + mmap: blktap_mmap, 15.220 +}; 15.221 + 15.222 +/* -------[ blktap module setup ]------------------------------------- */ 15.223 + 15.224 +static struct miscdevice blktap_miscdev = { 15.225 + .minor = BLKTAP_MINOR, 15.226 + .name = "blktap", 15.227 + .fops = &blktap_fops, 15.228 + .devfs_name = "misc/blktap", 15.229 +}; 15.230 + 15.231 +int blktap_init(void) 15.232 +{ 15.233 + int err; 15.234 + 15.235 + err = misc_register(&blktap_miscdev); 15.236 + if ( err != 0 ) 15.237 + { 15.238 + printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err); 15.239 + return err; 15.240 + } 15.241 + 15.242 + init_waitqueue_head(&blktap_wait); 15.243 + 15.244 + 15.245 + return 0; 15.246 +}
16.1 --- a/tools/libxutil/Makefile Wed Nov 24 11:51:49 2004 +0000 16.2 +++ b/tools/libxutil/Makefile Wed Nov 24 12:07:16 2004 +0000 16.3 @@ -5,11 +5,18 @@ CC = gcc 16.4 16.5 LIB_SRCS := 16.6 LIB_SRCS += allocate.c 16.7 +LIB_SRCS += enum.c 16.8 LIB_SRCS += file_stream.c 16.9 LIB_SRCS += gzip_stream.c 16.10 +LIB_SRCS += hash_table.c 16.11 LIB_SRCS += iostream.c 16.12 -#LIB_SRCS += sys_net.c 16.13 +LIB_SRCS += lexis.c 16.14 +LIB_SRCS += string_stream.c 16.15 +LIB_SRCS += sxpr.c 16.16 +LIB_SRCS += sxpr_parser.c 16.17 +LIB_SRCS += sys_net.c 16.18 LIB_SRCS += sys_string.c 16.19 +LIB_SRCS += util.c 16.20 16.21 LIB_OBJS := $(LIB_SRCS:.c=.o) 16.22 16.23 @@ -29,6 +36,7 @@ LIB_NAME := libxutil 16.24 LIB := $(LIB_NAME).so 16.25 LIB += $(LIB_NAME).so.$(MAJOR) 16.26 LIB += $(LIB_NAME).so.$(MAJOR).$(MINOR) 16.27 +LIB += $(LIB_NAME).a 16.28 16.29 all: check-for-zlib 16.30 $(MAKE) $(LIB) 16.31 @@ -42,6 +50,9 @@ all: check-for-zlib 16.32 $(LIB_NAME).so.$(MAJOR).$(MINOR): $(LIB_OBJS) 16.33 $(CC) -Wl,-soname -Wl,$(LIB_NAME).so.$(MAJOR) -shared -o $@ $^ 16.34 16.35 +$(LIB_NAME).a: $(LIB_OBJS) 16.36 + $(AR) rc $@ $^ 16.37 + 16.38 check-for-zlib: 16.39 @if [ ! -e /usr/include/zlib.h ]; then \ 16.40 echo "***********************************************************"; \
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/tools/libxutil/debug.h Wed Nov 24 12:07:16 2004 +0000 17.3 @@ -0,0 +1,72 @@ 17.4 +/* 17.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 17.6 + * 17.7 + * This library is free software; you can redistribute it and/or modify 17.8 + * it under the terms of the GNU Lesser General Public License as published by 17.9 + * the Free Software Foundation; either version 2.1 of the License, or 17.10 + * (at your option) any later version. 17.11 + * 17.12 + * This library is distributed in the hope that it will be useful, 17.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17.15 + * GNU Lesser General Public License for more details. 17.16 + * 17.17 + * You should have received a copy of the GNU Lesser General Public License 17.18 + * along with this library; if not, write to the Free Software 17.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17.20 + */ 17.21 +#ifndef _XUTIL_DEBUG_H_ 17.22 +#define _XUTIL_DEBUG_H_ 17.23 + 17.24 +#ifndef MODULE_NAME 17.25 +#define MODULE_NAME "" 17.26 +#endif 17.27 + 17.28 +#ifdef __KERNEL__ 17.29 +#include <linux/config.h> 17.30 +#include <linux/kernel.h> 17.31 + 17.32 +#ifdef DEBUG 17.33 + 17.34 +#define dprintf(fmt, args...) printk(KERN_DEBUG "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 17.35 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 17.36 +#define iprintf(fmt, args...) printk(KERN_INFO "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 17.37 +#define eprintf(fmt, args...) printk(KERN_ERR "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 17.38 + 17.39 +#else 17.40 + 17.41 +#define dprintf(fmt, args...) do {} while(0) 17.42 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args) 17.43 +#define iprintf(fmt, args...) printk(KERN_INFO "[INF] " MODULE_NAME fmt, ##args) 17.44 +#define eprintf(fmt, args...) printk(KERN_ERR "[ERR] " MODULE_NAME fmt, ##args) 17.45 + 17.46 +#endif 17.47 + 17.48 +#else 17.49 + 17.50 +#include <stdio.h> 17.51 + 17.52 +#ifdef DEBUG 17.53 + 17.54 +#define dprintf(fmt, args...) fprintf(stdout, "%d [DBG] " MODULE_NAME ">%s" fmt, getpid(), __FUNCTION__, ##args) 17.55 +#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args) 17.56 +#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args) 17.57 +#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args) 17.58 + 17.59 +#else 17.60 + 17.61 +#define dprintf(fmt, args...) do {} while(0) 17.62 +#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME fmt, getpid(), ##args) 17.63 +#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME fmt, getpid(), ##args) 17.64 +#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME fmt, getpid(), ##args) 17.65 + 17.66 +#endif 17.67 + 17.68 +#endif 17.69 + 17.70 +/** Print format for an IP address. 17.71 + * See NIPQUAD(), HIPQUAD() 17.72 + */ 17.73 +#define IPFMT "%u.%u.%u.%u" 17.74 + 17.75 +#endif /* ! _XUTIL_DEBUG_H_ */
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/tools/libxutil/enum.c Wed Nov 24 12:07:16 2004 +0000 18.3 @@ -0,0 +1,61 @@ 18.4 +/* 18.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com> 18.6 + * 18.7 + * This library is free software; you can redistribute it and/or modify 18.8 + * it under the terms of the GNU Lesser General Public License as 18.9 + * published by the Free Software Foundation; either version 2.1 of the 18.10 + * License, or (at your option) any later version. This library is 18.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 18.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 18.13 + * FITNESS FOR A PARTICULAR PURPOSE. 18.14 + * See the GNU Lesser General Public License for more details. 18.15 + * 18.16 + * You should have received a copy of the GNU Lesser General Public License 18.17 + * along with this library; if not, write to the Free Software Foundation, 18.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18.19 + */ 18.20 + 18.21 +#ifdef __KERNEL__ 18.22 +#include <linux/errno.h> 18.23 +#else 18.24 +#include <errno.h> 18.25 +#endif 18.26 + 18.27 +#include "sys_string.h" 18.28 +#include "enum.h" 18.29 + 18.30 +/** Map an enum name to its value using a table. 18.31 + * 18.32 + * @param name enum name 18.33 + * @param defs enum definitions 18.34 + * @return enum value or -1 if not known 18.35 + */ 18.36 +int enum_name_to_val(char *name, EnumDef *defs){ 18.37 + int val = -1; 18.38 + for(; defs->name; defs++){ 18.39 + if(!strcmp(defs->name, name)){ 18.40 + val = defs->val; 18.41 + break; 18.42 + } 18.43 + } 18.44 + return val; 18.45 +} 18.46 + 18.47 +/** Map an enum value to its name using a table. 18.48 + * 18.49 + * @param val enum value 18.50 + * @param defs enum definitions 18.51 + * @param defs_n number of definitions 18.52 + * @return enum name or NULL if not known 18.53 + */ 18.54 +char *enum_val_to_name(int val, EnumDef *defs){ 18.55 + char *name = NULL; 18.56 + for(; defs->name; defs++){ 18.57 + if(val == defs->val){ 18.58 + name = defs->name; 18.59 + break; 18.60 + } 18.61 + } 18.62 + return name; 18.63 +} 18.64 +
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/tools/libxutil/enum.h Wed Nov 24 12:07:16 2004 +0000 19.3 @@ -0,0 +1,30 @@ 19.4 +/* 19.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com> 19.6 + * 19.7 + * This library is free software; you can redistribute it and/or modify 19.8 + * it under the terms of the GNU Lesser General Public License as 19.9 + * published by the Free Software Foundation; either version 2.1 of the 19.10 + * License, or (at your option) any later version. This library is 19.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 19.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 19.13 + * FITNESS FOR A PARTICULAR PURPOSE. 19.14 + * See the GNU Lesser General Public License for more details. 19.15 + * 19.16 + * You should have received a copy of the GNU Lesser General Public License 19.17 + * along with this library; if not, write to the Free Software Foundation, 19.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19.19 + */ 19.20 + 19.21 +#ifndef _XUTIL_ENUM_H_ 19.22 +#define _XUTIL_ENUM_H_ 19.23 + 19.24 +/** Mapping of an enum value to a name. */ 19.25 +typedef struct EnumDef { 19.26 + int val; 19.27 + char *name; 19.28 +} EnumDef; 19.29 + 19.30 +extern int enum_name_to_val(char *name, EnumDef *defs); 19.31 +extern char *enum_val_to_name(int val, EnumDef *defs); 19.32 + 19.33 +#endif /* _XUTIL_ENUM_H_ */
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/tools/libxutil/hash_table.c Wed Nov 24 12:07:16 2004 +0000 20.3 @@ -0,0 +1,640 @@ 20.4 +/* 20.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 20.6 + * 20.7 + * This library is free software; you can redistribute it and/or modify 20.8 + * it under the terms of the GNU Lesser General Public License as published by 20.9 + * the Free Software Foundation; either version 2.1 of the License, or 20.10 + * (at your option) any later version. 20.11 + * 20.12 + * This library is distributed in the hope that it will be useful, 20.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 20.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20.15 + * GNU Lesser General Public License for more details. 20.16 + * 20.17 + * You should have received a copy of the GNU Lesser General Public License 20.18 + * along with this library; if not, write to the Free Software 20.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20.20 + */ 20.21 + 20.22 +#ifdef __KERNEL__ 20.23 +# include <linux/config.h> 20.24 +# include <linux/module.h> 20.25 +# include <linux/kernel.h> 20.26 +# include <linux/errno.h> 20.27 +#else 20.28 +# include <errno.h> 20.29 +# include <stddef.h> 20.30 +#endif 20.31 + 20.32 +//#include <limits.h> 20.33 + 20.34 +#include "allocate.h" 20.35 +#include "hash_table.h" 20.36 + 20.37 +/** @file 20.38 + * Base support for hashtables. 20.39 + * 20.40 + * Hash codes are reduced modulo the number of buckets to index tables, 20.41 + * so there is no need for hash functions to limit the range of hashcodes. 20.42 + * In fact it is assumed that hashcodes do not change when the number of 20.43 + * buckets in the table changes. 20.44 + */ 20.45 + 20.46 +/*==========================================================================*/ 20.47 +/** Number of bits in half a word. */ 20.48 +//#if __WORDSIZE == 64 20.49 +//#define HALF_WORD_BITS 32 20.50 +//#else 20.51 +#define HALF_WORD_BITS 16 20.52 +//#endif 20.53 + 20.54 +/** Mask for lo half of a word. On 32-bit this is 20.55 + * (1<<16) - 1 = 65535 = 0xffff 20.56 + * It's 4294967295 = 0xffffffff on 64-bit. 20.57 + */ 20.58 +#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1) 20.59 + 20.60 +/** Get the lo half of a word. */ 20.61 +#define LO_HALF(x) ((x) & LO_HALF_MASK) 20.62 + 20.63 +/** Get the hi half of a word. */ 20.64 +#define HI_HALF(x) ((x) >> HALF_WORD_BITS) 20.65 + 20.66 +/** Do a full hash on both inputs, using DES-style non-linear scrambling. 20.67 + * Both inputs are replaced with the results of the hash. 20.68 + * 20.69 + * @param pleft input/output word 20.70 + * @param pright input/output word 20.71 + */ 20.72 +void pseudo_des(unsigned long *pleft, unsigned long *pright){ 20.73 + // Bit-rich mixing constant. 20.74 + static const unsigned long a_mixer[] = { 20.75 + 0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, }; 20.76 + 20.77 + // Bit-rich mixing constant. 20.78 + static const unsigned long b_mixer[] = { 20.79 + 0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, }; 20.80 + 20.81 + // Number of iterations - must be 2 or 4. 20.82 + static const int ncycle = 4; 20.83 + //static const int ncycle = 2; 20.84 + 20.85 + unsigned long left = *pleft, right = *pright; 20.86 + unsigned long v, v_hi, v_lo; 20.87 + int i; 20.88 + 20.89 + for(i=0; i<ncycle; i++){ 20.90 + // Flip some bits in right to get v. 20.91 + v = right; 20.92 + v ^= a_mixer[i]; 20.93 + // Get lo and hi halves of v. 20.94 + v_lo = LO_HALF(v); 20.95 + v_hi = HI_HALF(v); 20.96 + // Non-linear mix of the halves of v. 20.97 + v = ((v_lo * v_lo) + ~(v_hi * v_hi)); 20.98 + // Swap the halves of v. 20.99 + v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS)); 20.100 + // Flip some bits. 20.101 + v ^= b_mixer[i]; 20.102 + // More non-linear mixing. 20.103 + v += (v_lo * v_hi); 20.104 + v ^= left; 20.105 + left = right; 20.106 + right = v; 20.107 + } 20.108 + *pleft = left; 20.109 + *pright = right; 20.110 +} 20.111 + 20.112 +/** Hash a string. 20.113 + * 20.114 + * @param s input to hash 20.115 + * @return hashcode 20.116 + */ 20.117 +Hashcode hash_string(char *s){ 20.118 + Hashcode h = 0; 20.119 + if(s){ 20.120 + for( ; *s; s++){ 20.121 + h = hash_2ul(h, *s); 20.122 + } 20.123 + } 20.124 + return h; 20.125 +} 20.126 + 20.127 +/** Get the bucket for a hashcode in a hash table. 20.128 + * 20.129 + * @param table to get bucket from 20.130 + * @param hashcode to get bucket for 20.131 + * @return bucket 20.132 + */ 20.133 +inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){ 20.134 + return table->buckets + (hashcode % table->buckets_n); 20.135 +} 20.136 + 20.137 +/** Initialize a hash table. 20.138 + * Can be safely called more than once. 20.139 + * 20.140 + * @param table to initialize 20.141 + */ 20.142 +void HashTable_init(HashTable *table){ 20.143 + int i; 20.144 + 20.145 + if(!table->init_done){ 20.146 + table->init_done = 1; 20.147 + table->next_id = 0; 20.148 + for(i=0; i<table->buckets_n; i++){ 20.149 + HTBucket *bucket = get_bucket(table, i); 20.150 + bucket->head = 0; 20.151 + bucket->count = 0; 20.152 + } 20.153 + table->entry_count = 0; 20.154 + } 20.155 +} 20.156 + 20.157 +/** Allocate a new hashtable. 20.158 + * If the number of buckets is not positive the default is used. 20.159 + * The number of buckets should usually be prime. 20.160 + * 20.161 + * @param buckets_n number of buckets 20.162 + * @return new hashtable or null 20.163 + */ 20.164 +HashTable *HashTable_new(int buckets_n){ 20.165 + HashTable *z = ALLOCATE(HashTable); 20.166 + if(!z) goto exit; 20.167 + if(buckets_n <= 0){ 20.168 + buckets_n = HT_BUCKETS_N; 20.169 + } 20.170 + z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket)); 20.171 + if(!z->buckets){ 20.172 + deallocate(z); 20.173 + z = 0; 20.174 + goto exit; 20.175 + } 20.176 + z->buckets_n = buckets_n; 20.177 + HashTable_init(z); 20.178 + exit: 20.179 + return z; 20.180 +} 20.181 + 20.182 +/** Free a hashtable. 20.183 + * Any entries are removed and freed. 20.184 + * 20.185 + * @param h hashtable (ignored if null) 20.186 + */ 20.187 +void HashTable_free(HashTable *h){ 20.188 + if(h){ 20.189 + HashTable_clear(h); 20.190 + deallocate(h->buckets); 20.191 + deallocate(h); 20.192 + } 20.193 +} 20.194 + 20.195 +/** Push an entry on the list in the bucket for a given hashcode. 20.196 + * 20.197 + * @param table to add entry to 20.198 + * @param hashcode for the entry 20.199 + * @param entry to add 20.200 + */ 20.201 +static inline void push_on_bucket(HashTable *table, Hashcode hashcode, 20.202 + HTEntry *entry){ 20.203 + HTBucket *bucket; 20.204 + HTEntry *old_head; 20.205 + 20.206 + bucket = get_bucket(table, hashcode); 20.207 + old_head = bucket->head; 20.208 + bucket->count++; 20.209 + bucket->head = entry; 20.210 + entry->next = old_head; 20.211 +} 20.212 + 20.213 +/** Change the number of buckets in a hashtable. 20.214 + * No-op if the number of buckets is not positive. 20.215 + * Existing entries are reallocated to buckets based on their hashcodes. 20.216 + * The table is unmodified if the number of buckets cannot be changed. 20.217 + * 20.218 + * @param table hashtable 20.219 + * @param buckets_n new number of buckets 20.220 + * @return 0 on success, error code otherwise 20.221 + */ 20.222 +int HashTable_set_buckets_n(HashTable *table, int buckets_n){ 20.223 + int err = 0; 20.224 + HTBucket *old_buckets = table->buckets; 20.225 + int old_buckets_n = table->buckets_n; 20.226 + int i; 20.227 + 20.228 + if(buckets_n <= 0){ 20.229 + err = -EINVAL; 20.230 + goto exit; 20.231 + } 20.232 + table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket)); 20.233 + if(!table->buckets){ 20.234 + err = -ENOMEM; 20.235 + table->buckets = old_buckets; 20.236 + goto exit; 20.237 + } 20.238 + table->buckets_n = buckets_n; 20.239 + for(i=0; i<old_buckets_n; i++){ 20.240 + HTBucket *bucket = old_buckets + i; 20.241 + HTEntry *entry, *next; 20.242 + for(entry = bucket->head; entry; entry = next){ 20.243 + next = entry->next; 20.244 + push_on_bucket(table, entry->hashcode, entry); 20.245 + } 20.246 + } 20.247 + deallocate(old_buckets); 20.248 + exit: 20.249 + return err; 20.250 +} 20.251 + 20.252 +/** Adjust the number of buckets so the table is neither too full nor too empty. 20.253 + * The table is unmodified if adjusting fails. 20.254 + * 20.255 + * @param table hash table 20.256 + * @param buckets_min minimum number of buckets (use default if 0 or negative) 20.257 + * @return 0 on success, error code otherwise 20.258 + */ 20.259 +int HashTable_adjust(HashTable *table, int buckets_min){ 20.260 + int buckets_n = 0; 20.261 + int err = 0; 20.262 + if(buckets_min <= 0) buckets_min = HT_BUCKETS_N; 20.263 + if(table->entry_count >= table->buckets_n){ 20.264 + // The table is dense - expand it. 20.265 + buckets_n = 2 * table->buckets_n; 20.266 + } else if((table->buckets_n > buckets_min) && 20.267 + (4 * table->entry_count < table->buckets_n)){ 20.268 + // The table is more than minimum size and sparse - shrink it. 20.269 + buckets_n = 2 * table->entry_count; 20.270 + if(buckets_n < buckets_min) buckets_n = buckets_min; 20.271 + } 20.272 + if(buckets_n){ 20.273 + err = HashTable_set_buckets_n(table, buckets_n); 20.274 + } 20.275 + return err; 20.276 +} 20.277 + 20.278 +/** Allocate a new entry for a given value. 20.279 + * 20.280 + * @param value to put in the entry 20.281 + * @return entry, or 0 on failure 20.282 + */ 20.283 +HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){ 20.284 + HTEntry *z = ALLOCATE(HTEntry); 20.285 + if(z){ 20.286 + z->hashcode = hashcode; 20.287 + z->key = key; 20.288 + z->value = value; 20.289 + } 20.290 + return z; 20.291 +} 20.292 + 20.293 +/** Free an entry. 20.294 + * 20.295 + * @param z entry to free 20.296 + */ 20.297 +inline void HTEntry_free(HTEntry *z){ 20.298 + if(z){ 20.299 + deallocate(z); 20.300 + } 20.301 +} 20.302 + 20.303 +/** Free an entry in a hashtable. 20.304 + * The table's entry_free_fn is used is defined, otherwise 20.305 + * the HTEntry itself is freed. 20.306 + * 20.307 + * @param table hashtable 20.308 + * @param entry to free 20.309 + */ 20.310 +inline void HashTable_free_entry(HashTable *table, HTEntry *entry){ 20.311 + if(!entry)return; 20.312 + if(table && table->entry_free_fn){ 20.313 + table->entry_free_fn(table, entry); 20.314 + } else { 20.315 + HTEntry_free(entry); 20.316 + } 20.317 +} 20.318 + 20.319 +/** Get the first entry satisfying a test from the bucket for the 20.320 + * given hashcode. 20.321 + * 20.322 + * @param table to look in 20.323 + * @param hashcode indicates the bucket 20.324 + * @param test_fn test to apply to elements 20.325 + * @param arg first argument to calls to test_fn 20.326 + * @return entry found, or 0 20.327 + */ 20.328 +inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode, 20.329 + TableTestFn *test_fn, TableArg arg){ 20.330 + HTBucket *bucket; 20.331 + HTEntry *entry = 0; 20.332 + HTEntry *next; 20.333 + 20.334 + bucket = get_bucket(table, hashcode); 20.335 + for(entry = bucket->head; entry; entry = next){ 20.336 + next = entry->next; 20.337 + if(test_fn(arg, table, entry)){ 20.338 + break; 20.339 + } 20.340 + } 20.341 + return entry; 20.342 +} 20.343 + 20.344 +/** Test hashtable keys for equality. 20.345 + * Uses the table's key_equal_fn if defined, otherwise pointer equality. 20.346 + * 20.347 + * @param key1 key to compare 20.348 + * @param key2 key to compare 20.349 + * @return 1 if equal, 0 otherwise 20.350 + */ 20.351 +inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){ 20.352 + return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2); 20.353 +} 20.354 + 20.355 +/** Compute the hashcode of a hashtable key. 20.356 + * The table's key_hash_fn is used if defined, otherwise the address of 20.357 + * the key is hashed. 20.358 + * 20.359 + * @param table hashtable 20.360 + * @param key to hash 20.361 + * @return hashcode 20.362 + */ 20.363 +inline Hashcode HashTable_key_hash(HashTable *table, void *key){ 20.364 + return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key)); 20.365 +} 20.366 + 20.367 +/** Test if an entry has a given key. 20.368 + * 20.369 + * @param arg containing key to test for 20.370 + * @param table the entry is in 20.371 + * @param entry to test 20.372 + * @return 1 if the entry has the key, 0 otherwise 20.373 + */ 20.374 +static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){ 20.375 + return HashTable_key_equal(table, arg.ptr, entry->key); 20.376 +} 20.377 + 20.378 +/** Get an entry with a given key. 20.379 + * 20.380 + * @param table to search 20.381 + * @param key to look for 20.382 + * @return entry if found, null otherwise 20.383 + */ 20.384 +#if 0 20.385 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){ 20.386 + TableArg arg = { ptr: key }; 20.387 + return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg); 20.388 +} 20.389 +#else 20.390 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){ 20.391 + Hashcode hashcode; 20.392 + HTBucket *bucket; 20.393 + HTEntry *entry = 0; 20.394 + HTEntry *next; 20.395 + 20.396 + hashcode = HashTable_key_hash(table, key); 20.397 + bucket = get_bucket(table, hashcode); 20.398 + for(entry = bucket->head; entry; entry = next){ 20.399 + next = entry->next; 20.400 + if(HashTable_key_equal(table, key, entry->key)){ 20.401 + break; 20.402 + } 20.403 + } 20.404 + return entry; 20.405 +} 20.406 +#endif 20.407 + 20.408 +/** Get the value of an entry with a given key. 20.409 + * 20.410 + * @param table to search 20.411 + * @param key to look for 20.412 + * @return value if an entry was found, null otherwise 20.413 + */ 20.414 +inline void * HashTable_get(HashTable *table, void *key){ 20.415 + HTEntry *entry = HashTable_get_entry(table, key); 20.416 + return (entry ? entry->value : 0); 20.417 +} 20.418 + 20.419 +/** Print the buckets in a table. 20.420 + * 20.421 + * @param table to print 20.422 + */ 20.423 +void show_buckets(HashTable *table, IOStream *io){ 20.424 + int i,j ; 20.425 + IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n); 20.426 + for(i=0; i<table->buckets_n; i++){ 20.427 + if(0 || table->buckets[i].count>0){ 20.428 + IOStream_print(io, "bucket %3d %3d %10p ", i, 20.429 + table->buckets[i].count, 20.430 + table->buckets[i].head); 20.431 + for(j = table->buckets[i].count; j>0; j--){ 20.432 + IOStream_print(io, "+"); 20.433 + } 20.434 + IOStream_print(io, "\n"); 20.435 + } 20.436 + } 20.437 + HashTable_print(table, io); 20.438 +} 20.439 + 20.440 +/** Print an entry in a table. 20.441 + * 20.442 + * @param entry to print 20.443 + * @param arg a pointer to an IOStream to print to 20.444 + * @return 0 20.445 + */ 20.446 +static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){ 20.447 + IOStream *io = (IOStream*)arg.ptr; 20.448 + IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n", 20.449 + entry->hashcode % table->buckets_n, 20.450 + entry->hashcode, 20.451 + entry->index, 20.452 + entry, entry->key, entry->value); 20.453 + return 0; 20.454 +} 20.455 + 20.456 +/** Print a hash table. 20.457 + * 20.458 + * @param table to print 20.459 + */ 20.460 +void HashTable_print(HashTable *table, IOStream *io){ 20.461 + IOStream_print(io, "{\n"); 20.462 + HashTable_map(table, print_entry, (TableArg){ ptr: io }); 20.463 + IOStream_print(io, "}\n"); 20.464 +} 20.465 +/*==========================================================================*/ 20.466 + 20.467 +/** Get the next entry id to use for a table. 20.468 + * 20.469 + * @param table hash table 20.470 + * @return non-zero entry id 20.471 + */ 20.472 +static inline unsigned long get_next_id(HashTable *table){ 20.473 + unsigned long id; 20.474 + 20.475 + if(table->next_id == 0){ 20.476 + table->next_id = 1; 20.477 + } 20.478 + id = table->next_id++; 20.479 + return id; 20.480 +} 20.481 + 20.482 +/** Add an entry to the bucket for the 20.483 + * given hashcode. 20.484 + * 20.485 + * @param table to insert in 20.486 + * @param hashcode indicates the bucket 20.487 + * @param key to add an entry for 20.488 + * @param value to add an entry for 20.489 + * @return entry on success, 0 on failure 20.490 + */ 20.491 +inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){ 20.492 + HTEntry *entry = HTEntry_new(hashcode, key, value); 20.493 + if(entry){ 20.494 + entry->index = get_next_id(table); 20.495 + push_on_bucket(table, hashcode, entry); 20.496 + table->entry_count++; 20.497 + } 20.498 + return entry; 20.499 +} 20.500 + 20.501 +/** Move the front entry for a bucket to the correct point in the bucket order as 20.502 + * defined by the order function. If this is called every time a new entry is added 20.503 + * the bucket will be maintained in sorted order. 20.504 + * 20.505 + * @param table to modify 20.506 + * @param hashcode indicates the bucket 20.507 + * @param order entry comparison function 20.508 + * @return 0 if an entry was moved, 1 if not 20.509 + */ 20.510 +int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){ 20.511 + HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL; 20.512 + HTBucket *bucket; 20.513 + int err = 1; 20.514 + 20.515 + bucket = get_bucket(table, hashcode); 20.516 + new_entry = bucket->head; 20.517 + if(!new_entry || !new_entry->next) goto exit; 20.518 + for(entry = new_entry->next; entry; prev = entry, entry = entry->next){ 20.519 + if(order(new_entry, entry) <= 0) break; 20.520 + } 20.521 + if(prev){ 20.522 + err = 0; 20.523 + bucket->head = new_entry->next; 20.524 + new_entry->next = entry; 20.525 + prev->next = new_entry; 20.526 + } 20.527 + exit: 20.528 + return err; 20.529 +} 20.530 + 20.531 +/** Add an entry to a hashtable. 20.532 + * The entry is added to the bucket for its key's hashcode. 20.533 + * 20.534 + * @param table to insert in 20.535 + * @param key to add an entry for 20.536 + * @param value to add an entry for 20.537 + * @return entry on success, 0 on failure 20.538 + */ 20.539 +inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){ 20.540 + return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value); 20.541 +} 20.542 + 20.543 + 20.544 +/** Remove entries satisfying a test from the bucket for the 20.545 + * given hashcode. 20.546 + * 20.547 + * @param table to remove from 20.548 + * @param hashcode indicates the bucket 20.549 + * @param test_fn test to apply to elements 20.550 + * @param arg first argument to calls to test_fn 20.551 + * @return number of entries removed 20.552 + */ 20.553 +inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode, 20.554 + TableTestFn *test_fn, TableArg arg){ 20.555 + HTBucket *bucket; 20.556 + HTEntry *entry, *prev = 0, *next; 20.557 + int removed_count = 0; 20.558 + 20.559 + bucket = get_bucket(table, hashcode); 20.560 + for(entry = bucket->head; entry; entry = next){ 20.561 + next = entry->next; 20.562 + if(test_fn(arg, table, entry)){ 20.563 + if(prev){ 20.564 + prev->next = next; 20.565 + } else { 20.566 + bucket->head = next; 20.567 + } 20.568 + bucket->count--; 20.569 + table->entry_count--; 20.570 + removed_count++; 20.571 + HashTable_free_entry(table, entry); 20.572 + entry = 0; 20.573 + } 20.574 + prev = entry; 20.575 + } 20.576 + return removed_count; 20.577 +} 20.578 + 20.579 +/** Remove entries with a given key. 20.580 + * 20.581 + * @param table to remove from 20.582 + * @param key of entries to remove 20.583 + * @return number of entries removed 20.584 + */ 20.585 +inline int HashTable_remove(HashTable *table, void *key){ 20.586 +#if 1 20.587 + Hashcode hashcode; 20.588 + HTBucket *bucket; 20.589 + HTEntry *entry, *prev = 0, *next; 20.590 + int removed_count = 0; 20.591 + 20.592 + hashcode = HashTable_key_hash(table, key); 20.593 + bucket = get_bucket(table, hashcode); 20.594 + for(entry = bucket->head; entry; entry = next){ 20.595 + next = entry->next; 20.596 + if(HashTable_key_equal(table, key, entry->key)){ 20.597 + if(prev){ 20.598 + prev->next = next; 20.599 + } else { 20.600 + bucket->head = next; 20.601 + } 20.602 + bucket->count--; 20.603 + table->entry_count--; 20.604 + removed_count++; 20.605 + HashTable_free_entry(table, entry); 20.606 + entry = 0; 20.607 + } 20.608 + prev = entry; 20.609 + } 20.610 + return removed_count; 20.611 +#else 20.612 + return HashTable_remove_entry(table, HashTable_key_hash(table, key), 20.613 + has_key, (TableArg){ ptr: key}); 20.614 +#endif 20.615 +} 20.616 + 20.617 +/** Remove (and free) all the entries in a bucket. 20.618 + * 20.619 + * @param bucket to clear 20.620 + */ 20.621 +static inline void bucket_clear(HashTable *table, HTBucket *bucket){ 20.622 + HTEntry *entry, *next; 20.623 + 20.624 + for(entry = bucket->head; entry; entry = next){ 20.625 + next = entry->next; 20.626 + HashTable_free_entry(table, entry); 20.627 + } 20.628 + bucket->head = 0; 20.629 + table->entry_count -= bucket->count; 20.630 + bucket->count = 0; 20.631 +} 20.632 + 20.633 +/** Remove (and free) all the entries in a table. 20.634 + * 20.635 + * @param table to clear 20.636 + */ 20.637 +void HashTable_clear(HashTable *table){ 20.638 + int i, n = table->buckets_n; 20.639 + 20.640 + for(i=0; i<n; i++){ 20.641 + bucket_clear(table, table->buckets + i); 20.642 + } 20.643 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/tools/libxutil/hash_table.h Wed Nov 24 12:07:16 2004 +0000 21.3 @@ -0,0 +1,294 @@ 21.4 +/* 21.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 21.6 + * 21.7 + * This library is free software; you can redistribute it and/or modify 21.8 + * it under the terms of the GNU Lesser General Public License as published by 21.9 + * the Free Software Foundation; either version 2.1 of the License, or 21.10 + * (at your option) any later version. 21.11 + * 21.12 + * This library is distributed in the hope that it will be useful, 21.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21.15 + * GNU Lesser General Public License for more details. 21.16 + * 21.17 + * You should have received a copy of the GNU Lesser General Public License 21.18 + * along with this library; if not, write to the Free Software 21.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21.20 + */ 21.21 + 21.22 +#ifndef _XUTIL_HASH_TABLE_H_ 21.23 +#define _XUTIL_HASH_TABLE_H_ 21.24 + 21.25 +#include "iostream.h" 21.26 + 21.27 +typedef unsigned long Hashcode; 21.28 + 21.29 +/** Type used to pass parameters to table functions. */ 21.30 +typedef union TableArg { 21.31 + unsigned long ul; 21.32 + void *ptr; 21.33 +} TableArg; 21.34 + 21.35 +/** An entry in a bucket list. */ 21.36 +typedef struct HTEntry { 21.37 + /** Hashcode of the entry's key. */ 21.38 + Hashcode hashcode; 21.39 + /** Identifier for this entry in the table. */ 21.40 + int index; 21.41 + /** The key for this entry. */ 21.42 + void *key; 21.43 + /** The value in this entry. */ 21.44 + void *value; 21.45 + /** The next entry in the list. */ 21.46 + struct HTEntry *next; 21.47 +} HTEntry; 21.48 + 21.49 +/** A bucket in a rule table. */ 21.50 +typedef struct HTBucket { 21.51 + /** Number of entries in the bucket. */ 21.52 + int count; 21.53 + /** First entry in the bucket (may be null). */ 21.54 + HTEntry *head; 21.55 +} HTBucket; 21.56 + 21.57 +/** Default number of buckets in a hash table. 21.58 + * You want enough buckets so the lists in the buckets will typically be short. 21.59 + * It's a good idea if this is prime, since that will help to spread hashcodes 21.60 + * around the table. 21.61 + */ 21.62 +//#define HT_BUCKETS_N 1 21.63 +//#define HT_BUCKETS_N 3 21.64 +//#define HT_BUCKETS_N 7 21.65 +//#define HT_BUCKETS_N 17 21.66 +//#define HT_BUCKETS_N 97 21.67 +//#define HT_BUCKETS_N 211 21.68 +//#define HT_BUCKETS_N 401 21.69 +#define HT_BUCKETS_N 1021 21.70 + 21.71 +typedef struct HashTable HashTable; 21.72 + 21.73 +/** Type for a function used to select table entries. */ 21.74 +typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry); 21.75 + 21.76 +/** Type for a function to map over table entries. */ 21.77 +typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry); 21.78 + 21.79 +/** Type for a function to free table entries. */ 21.80 +typedef void TableFreeFn(HashTable *table, HTEntry *entry); 21.81 + 21.82 +/** Type for a function to hash table keys. */ 21.83 +typedef Hashcode TableHashFn(void *key); 21.84 + 21.85 +/** Type for a function to test table keys for equality. */ 21.86 +typedef int TableEqualFn(void *key1, void *key2); 21.87 + 21.88 +/** Type for a function to order table entries. */ 21.89 +typedef int TableOrderFn(HTEntry *e1, HTEntry *e2); 21.90 + 21.91 +/** General hash table. 21.92 + * A hash table with a list in each bucket. 21.93 + * Functions can be supplied for freeing entries, hashing keys, and comparing keys. 21.94 + * These all default to 0, when default behaviour treating keys as integers is used. 21.95 + */ 21.96 +struct HashTable { 21.97 + /** Flag indicating whether the table has been initialised. */ 21.98 + int init_done; 21.99 + /** Next value for the id field in inserted rules. */ 21.100 + unsigned long next_id; 21.101 + /** Number of buckets in the bucket array. */ 21.102 + int buckets_n; 21.103 + /** Array of buckets, each with its own list. */ 21.104 + HTBucket *buckets; 21.105 + /** Number of entries in the table. */ 21.106 + int entry_count; 21.107 + /** Function to free keys and values in entries. */ 21.108 + TableFreeFn *entry_free_fn; 21.109 + /** Function to hash keys. */ 21.110 + TableHashFn *key_hash_fn; 21.111 + /** Function to compare keys for equality. */ 21.112 + TableEqualFn *key_equal_fn; 21.113 + /** Place for the user of the table to hang extra data. */ 21.114 + void *user_data; 21.115 +}; 21.116 + 21.117 +extern HashTable *HashTable_new(int bucket_n); 21.118 +extern void HashTable_free(HashTable *table); 21.119 +extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value); 21.120 +extern void HTEntry_free(HTEntry *entry); 21.121 +extern int HashTable_set_bucket_n(HashTable *table, int bucket_n); 21.122 +extern void HashTable_clear(HashTable *table); 21.123 +extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value); 21.124 +extern HTEntry * HashTable_get_entry(HashTable *table, void *key); 21.125 +extern HTEntry * HashTable_add(HashTable *table, void *key, void *value); 21.126 +extern void * HashTable_get(HashTable *table, void *key); 21.127 +extern int HashTable_remove(HashTable *table, void *key); 21.128 +extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode, 21.129 + TableTestFn *test_fn, TableArg arg); 21.130 +extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode, 21.131 + TableTestFn *test_fn, TableArg arg); 21.132 +//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg); 21.133 +extern void HashTable_print(HashTable *table, IOStream *out); 21.134 +extern int HashTable_set_buckets_n(HashTable *table, int buckets_n); 21.135 +extern int HashTable_adjust(HashTable *table, int buckets_min); 21.136 +extern void pseudo_des(unsigned long *pleft, unsigned long *pright); 21.137 +extern Hashcode hash_string(char *s); 21.138 + 21.139 +extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order); 21.140 + 21.141 +/** Control whether to use hashing based on DES or simple 21.142 + * hashing. DES hashing is `more random' but much more expensive. 21.143 + */ 21.144 +#define HASH_PSEUDO_DES 0 21.145 + 21.146 +/** Hash a long using a quick and dirty linear congruential random number generator. 21.147 + * See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator". 21.148 + * 21.149 + * @param a value to hash 21.150 + * @return hashed input 21.151 + */ 21.152 +static inline unsigned long lcrng_hash(unsigned long a){ 21.153 + return (1664525L * a + 1013904223L); 21.154 +} 21.155 + 21.156 +/** Hash an unsigned long. 21.157 + * 21.158 + * @param a input to hash 21.159 + * @return hashcode 21.160 + */ 21.161 +static inline Hashcode hash_ul(unsigned long a){ 21.162 +#if HASH_PSEUDO_DES 21.163 + unsigned long left = a; 21.164 + unsigned long right = 0L; 21.165 + pseudo_des(&left, &right); 21.166 + return right; 21.167 +#else 21.168 + a = lcrng_hash(a); 21.169 + a = lcrng_hash(a); 21.170 + return a; 21.171 +#endif 21.172 +} 21.173 + 21.174 +/** Hash two unsigned longs together. 21.175 + * 21.176 + * @param a input to hash 21.177 + * @param b input to hash 21.178 + * @return hashcode 21.179 + */ 21.180 +static inline Hashcode hash_2ul(unsigned long a, unsigned long b){ 21.181 +#if HASH_PSEUDO_DES 21.182 + unsigned long left = a; 21.183 + unsigned long right = b; 21.184 + pseudo_des(&left, &right); 21.185 + return right; 21.186 +#else 21.187 + a = lcrng_hash(a); 21.188 + a ^= b; 21.189 + a = lcrng_hash(a); 21.190 + return a; 21.191 +#endif 21.192 +} 21.193 + 21.194 +/** Hash a hashcode and an unsigned long together. 21.195 + * 21.196 + * @param a input hashcode 21.197 + * @param b input to hash 21.198 + * @return hashcode 21.199 + */ 21.200 +static inline Hashcode hash_hul(Hashcode a, unsigned long b){ 21.201 +#if HASH_PSEUDO_DES 21.202 + unsigned long left = a; 21.203 + unsigned long right = b; 21.204 + pseudo_des(&left, &right); 21.205 + return right; 21.206 +#else 21.207 + a ^= b; 21.208 + a = lcrng_hash(a); 21.209 + return a; 21.210 +#endif 21.211 +} 21.212 + 21.213 +/** Macro to declare variables for HashTable_for_each() to use. 21.214 + * 21.215 + * @param entry variable that is set to entries in the table 21.216 + */ 21.217 +#define HashTable_for_decl(entry) \ 21.218 + HashTable *_var_table; \ 21.219 + HTBucket *_var_bucket; \ 21.220 + HTBucket *_var_end; \ 21.221 + HTEntry *_var_next; \ 21.222 + HTEntry *entry 21.223 + 21.224 +/** Macro to iterate over the entries in a hashtable. 21.225 + * Must be in a scope where HashTable_for_decl() has been used to declare 21.226 + * variables for it to use. 21.227 + * The variable 'entry' is iterated over entries in the table. 21.228 + * The code produced is syntactically a loop, so it must be followed by 21.229 + * a loop body, typically some statements in braces: 21.230 + * HashTable_for_each(entry, table){ ...loop body... } 21.231 + * 21.232 + * HashTable_for_each() and HashTable_for_decl() cannot be used for nested 21.233 + * loops as variables will clash. 21.234 + * 21.235 + * @note The simplest way to code a direct loop over the entries in a hashtable 21.236 + * is to use a loop over the buckets, with a nested loop over the entries 21.237 + * in a bucket. Using this approach in a macro means the macro contains 21.238 + * an opening brace, and calls to it must be followed by 2 braces! 21.239 + * To avoid this the code has been restructured so that it is a for loop. 21.240 + * So that statements could be used in the test expression of the for loop, 21.241 + * we have used the gcc statement expression extension ({ ... }). 21.242 + * 21.243 + * @param entry variable to iterate over the entries 21.244 + * @param table to iterate over (non-null) 21.245 + */ 21.246 +#define HashTable_for_each(entry, table) \ 21.247 + _var_table = table; \ 21.248 + _var_bucket = _var_table->buckets; \ 21.249 + _var_end = _var_bucket + _var_table->buckets_n; \ 21.250 + for(entry=0, _var_next=0; \ 21.251 + ({ if(_var_next){ \ 21.252 + entry = _var_next; \ 21.253 + _var_next = entry->next; \ 21.254 + } else { \ 21.255 + while(_var_bucket < _var_end){ \ 21.256 + entry = _var_bucket->head; \ 21.257 + _var_bucket++; \ 21.258 + if(entry){ \ 21.259 + _var_next = entry->next; \ 21.260 + break; \ 21.261 + } \ 21.262 + } \ 21.263 + }; \ 21.264 + entry; }); \ 21.265 + entry = _var_next ) 21.266 + 21.267 +/** Map a function over the entries in a table. 21.268 + * Mapping stops when the function returns a non-zero value. 21.269 + * Uses the gcc statement expression extension ({ ... }). 21.270 + * 21.271 + * @param table to map over 21.272 + * @param fn function to apply to entries 21.273 + * @param arg first argument to call the function with 21.274 + * @return 0 if fn always returned 0, first non-zero value otherwise 21.275 + */ 21.276 +#define HashTable_map(table, fn, arg) \ 21.277 + ({ HashTable_for_decl(_var_entry); \ 21.278 + TableArg _var_arg = arg; \ 21.279 + int _var_value = 0; \ 21.280 + HashTable_for_each(_var_entry, table){ \ 21.281 + if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \ 21.282 + } \ 21.283 + _var_value; }) 21.284 + 21.285 +/** Cast x to the type for a key or value in a hash table. 21.286 + * This avoids compiler warnings when using short integers 21.287 + * as keys or values (especially on 64-bit platforms). 21.288 + */ 21.289 +#define HKEY(x) ((void*)(unsigned long)(x)) 21.290 + 21.291 +/** Cast x from the type for a key or value in a hash table. 21.292 + * to an unsigned long. This avoids compiler warnings when using 21.293 + * short integers as keys or values (especially on 64-bit platforms). 21.294 + */ 21.295 +#define HVAL(x) ((unsigned long)(x)) 21.296 + 21.297 +#endif /* !_XUTIL_HASH_TABLE_H_ */
22.1 --- a/tools/libxutil/iostream.c Wed Nov 24 11:51:49 2004 +0000 22.2 +++ b/tools/libxutil/iostream.c Wed Nov 24 12:07:16 2004 +0000 22.3 @@ -1,3 +1,21 @@ 22.4 +/* 22.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 22.6 + * 22.7 + * This library is free software; you can redistribute it and/or modify 22.8 + * it under the terms of the GNU Lesser General Public License as published by 22.9 + * the Free Software Foundation; either version 2.1 of the License, or 22.10 + * (at your option) any later version. 22.11 + * 22.12 + * This library is distributed in the hope that it will be useful, 22.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22.15 + * GNU Lesser General Public License for more details. 22.16 + * 22.17 + * You should have received a copy of the GNU Lesser General Public License 22.18 + * along with this library; if not, write to the Free Software 22.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22.20 + */ 22.21 + 22.22 #include "iostream.h" 22.23 #include "sys_string.h" 22.24
23.1 --- a/tools/libxutil/iostream.h Wed Nov 24 11:51:49 2004 +0000 23.2 +++ b/tools/libxutil/iostream.h Wed Nov 24 12:07:16 2004 +0000 23.3 @@ -1,14 +1,34 @@ 23.4 -#ifndef _XC_LINUX_SAVE_H_ 23.5 -#define _XC_LINUX_SAVE_H_ 23.6 +/* 23.7 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 23.8 + * 23.9 + * This library is free software; you can redistribute it and/or modify 23.10 + * it under the terms of the GNU Lesser General Public License as published by 23.11 + * the Free Software Foundation; either version 2.1 of the License, or 23.12 + * (at your option) any later version. 23.13 + * 23.14 + * This library is distributed in the hope that it will be useful, 23.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 23.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23.17 + * GNU Lesser General Public License for more details. 23.18 + * 23.19 + * You should have received a copy of the GNU Lesser General Public License 23.20 + * along with this library; if not, write to the Free Software 23.21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23.22 + */ 23.23 + 23.24 +#ifndef _XUTIL_IOSTREAM_H_ 23.25 +#define _XUTIL_IOSTREAM_H_ 23.26 23.27 #include <stdarg.h> 23.28 -#include <stdint.h> 23.29 -#include <stddef.h> 23.30 23.31 #ifdef __KERNEL__ 23.32 +#include <linux/config.h> 23.33 +#include <linux/types.h> 23.34 #include <linux/errno.h> 23.35 #else 23.36 #include <errno.h> 23.37 +#include <stdint.h> 23.38 +#include <stddef.h> 23.39 #endif 23.40 23.41 #include "allocate.h" 23.42 @@ -240,4 +260,4 @@ static inline int IOStream_get_written(I 23.43 } 23.44 23.45 23.46 -#endif /* ! _XC_LINUX_SAVE_H_ */ 23.47 +#endif /* ! _XUTIL_IOSTREAM_H_ */
24.1 --- a/tools/libxutil/kernel_stream.c Wed Nov 24 11:51:49 2004 +0000 24.2 +++ b/tools/libxutil/kernel_stream.c Wed Nov 24 12:07:16 2004 +0000 24.3 @@ -50,7 +50,7 @@ typedef struct KernelData { 24.4 char buf[BUF_N]; 24.5 } KernelData; 24.6 24.7 -static int kernel_write(IOStream *s, const char *msg, int n); 24.8 +static int kernel_write(IOStream *s, const void *msg, size_t n); 24.9 static void kernel_free(IOStream *s); 24.10 static void kernel_stream_lock(IOStream *s); 24.11 static void kernel_stream_unlock(IOStream *s); 24.12 @@ -145,13 +145,13 @@ void kernel_stream_unlock(IOStream *s){ 24.13 * @param args print arguments 24.14 * @return result of the print 24.15 */ 24.16 -static int kernel_write(IOStream *stream, const char *buf, int n){ 24.17 +static int kernel_write(IOStream *stream, const void *buf, size_t n){ 24.18 KernelData *kdata = get_kernel_data(stream); 24.19 int k; 24.20 k = kdata->buf_n - 1; 24.21 if(n < k) k = n; 24.22 memcpy(kdata->buf, buf, k); 24.23 - kdata->buf[k] = '\0' 24.24 + kdata->buf[k] = '\0'; 24.25 printk(kdata->buf); 24.26 return k; 24.27 } 24.28 @@ -167,7 +167,7 @@ static void kernel_free(IOStream *io){ 24.29 KernelData *kdata; 24.30 if(io == &iokernel) return; 24.31 kdata = get_kernel_data(io); 24.32 - zero(kdata, sizeof(*kdata)); 24.33 + memset(kdata, 0, sizeof(*kdata)); 24.34 deallocate(kdata); 24.35 } 24.36 #endif /* __KERNEL__ */
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/tools/libxutil/lexis.c Wed Nov 24 12:07:16 2004 +0000 25.3 @@ -0,0 +1,94 @@ 25.4 +/* 25.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 25.6 + * 25.7 + * This library is free software; you can redistribute it and/or modify 25.8 + * it under the terms of the GNU Lesser General Public License as 25.9 + * published by the Free Software Foundation; either version 2.1 of the 25.10 + * License, or (at your option) any later version. This library is 25.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 25.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 25.13 + * FITNESS FOR A PARTICULAR PURPOSE. 25.14 + * See the GNU Lesser General Public License for more details. 25.15 + * 25.16 + * You should have received a copy of the GNU Lesser General Public License 25.17 + * along with this library; if not, write to the Free Software Foundation, 25.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25.19 + */ 25.20 + 25.21 +/** @file 25.22 + * Lexical analysis. 25.23 + */ 25.24 + 25.25 +#include "sys_string.h" 25.26 +#include "lexis.h" 25.27 +#include <errno.h> 25.28 + 25.29 +/** Check if a value lies in a (closed) range. 25.30 + * 25.31 + * @param x value to test 25.32 + * @param lo low end of the range 25.33 + * @param hi high end of the range 25.34 + * @return 1 if x is in the interval [lo, hi], 0 otherwise 25.35 + */ 25.36 +inline static int in_range(int x, int lo, int hi){ 25.37 + return (lo <= x) && (x <= hi); 25.38 +} 25.39 + 25.40 +/** Determine if a string is an (unsigned) decimal number. 25.41 + * 25.42 + * @param s pointer to characters to test 25.43 + * @param n length of string 25.44 + * @return 1 if s is a decimal number, 0 otherwise. 25.45 + */ 25.46 +int is_decimal_number(const char *s, int n){ 25.47 + int i; 25.48 + if(n <= 0)return 0; 25.49 + for(i = 0; i < n; i++){ 25.50 + if(!in_decimal_digit_class(s[i])) return 0; 25.51 + } 25.52 + return 1; 25.53 +} 25.54 + 25.55 +/** Determine if a string is a hex number. 25.56 + * Hex numbers are 0, or start with 0x or 0X followed 25.57 + * by a non-zero number of hex digits (0-9,a-f,A-F). 25.58 + * 25.59 + * @param s pointer to characters to test 25.60 + * @param n length of string 25.61 + * @return 1 if s is a hex number, 0 otherwise. 25.62 + */ 25.63 +int is_hex_number(const char *s, int n){ 25.64 + int i; 25.65 + if(n <= 0) return 0; 25.66 + if(n == 1){ 25.67 + return s[0]=='0'; 25.68 + } 25.69 + if(n <= 3) return 0; 25.70 + if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0; 25.71 + for(i = 2; i < n; i++){ 25.72 + if(!in_hex_digit_class(s[i])) return 0; 25.73 + } 25.74 + return 1; 25.75 +} 25.76 + 25.77 +/** Test if a string matches a keyword. 25.78 + * The comparison is case-insensitive. 25.79 + * The comparison fails if either argument is null. 25.80 + * 25.81 + * @param s string 25.82 + * @param k keyword 25.83 + * @return 1 if they match, 0 otherwise 25.84 + */ 25.85 +int is_keyword(const char *s, const char *k){ 25.86 + return s && k && !strcasecmp(s, k); 25.87 +} 25.88 + 25.89 +/** Test if a string matches a character. 25.90 + * 25.91 + * @param s string 25.92 + * @param c character (non-null) 25.93 + * @return 1 if s contains exactly c, 0 otherwise 25.94 + */ 25.95 +int is_keychar(const char *s, char c){ 25.96 + return c && (s[0] == c) && !s[1]; 25.97 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/tools/libxutil/lexis.h Wed Nov 24 12:07:16 2004 +0000 26.3 @@ -0,0 +1,128 @@ 26.4 +/* 26.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 26.6 + * 26.7 + * This library is free software; you can redistribute it and/or modify 26.8 + * it under the terms of the GNU Lesser General Public License as 26.9 + * published by the Free Software Foundation; either version 2.1 of the 26.10 + * License, or (at your option) any later version. This library is 26.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 26.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 26.13 + * FITNESS FOR A PARTICULAR PURPOSE. 26.14 + * See the GNU Lesser General Public License for more details. 26.15 + * 26.16 + * You should have received a copy of the GNU Lesser General Public License 26.17 + * along with this library; if not, write to the Free Software Foundation, 26.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26.19 + */ 26.20 + 26.21 +#ifndef _XUTIL_LEXIS_H_ 26.22 +#define _XUTIL_LEXIS_H_ 26.23 + 26.24 +#include "sys_string.h" 26.25 + 26.26 +#ifdef __KERNEL__ 26.27 +# include <linux/ctype.h> 26.28 +#else 26.29 +# include <ctype.h> 26.30 +#endif 26.31 + 26.32 +/** @file 26.33 + * Lexical analysis. 26.34 + */ 26.35 + 26.36 +/** Class of characters treated as space. */ 26.37 +#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 }) 26.38 + 26.39 +/** Class of separator characters. */ 26.40 +#define sep_class "{}()<>[]@!;" 26.41 + 26.42 +#define comment_class "#" 26.43 + 26.44 +/** Determine if a character is in a given class. 26.45 + * 26.46 + * @param c character to test 26.47 + * @param s null-terminated string of characters in the class 26.48 + * @return 1 if c is in the class, 0 otherwise. 26.49 + */ 26.50 +static inline int in_class(int c, const char *s){ 26.51 + return s && (strchr(s, c) != 0); 26.52 +} 26.53 + 26.54 +/** Determine if a character is in the space class. 26.55 + * 26.56 + * @param c character to test 26.57 + * @return 1 if c is in the class, 0 otherwise. 26.58 + */ 26.59 +static inline int in_space_class(int c){ 26.60 + return in_class(c, space_class); 26.61 +} 26.62 + 26.63 +static inline int in_comment_class(int c){ 26.64 + return in_class(c, comment_class); 26.65 +} 26.66 + 26.67 +/** Determine if a character is in the separator class. 26.68 + * Separator characters terminate tokens, and do not need space 26.69 + * to separate them. 26.70 + * 26.71 + * @param c character to test 26.72 + * @return 1 if c is in the class, 0 otherwise. 26.73 + */ 26.74 +static inline int in_sep_class(int c){ 26.75 + return in_class(c, sep_class); 26.76 +} 26.77 + 26.78 +/** Determine if a character is in the alpha class. 26.79 + * 26.80 + * @param c character to test 26.81 + * @return 1 if c is in the class, 0 otherwise. 26.82 + */ 26.83 +static inline int in_alpha_class(int c){ 26.84 + return isalpha(c); 26.85 +} 26.86 + 26.87 +/** Determine if a character is in the octal digit class. 26.88 + * 26.89 + * @param c character to test 26.90 + * @return 1 if c is in the class, 0 otherwise. 26.91 + */ 26.92 +static inline int in_octal_digit_class(int c){ 26.93 + return '0' <= c && c <= '7'; 26.94 +} 26.95 + 26.96 +/** Determine if a character is in the decimal digit class. 26.97 + * 26.98 + * @param c character to test 26.99 + * @return 1 if c is in the class, 0 otherwise. 26.100 + */ 26.101 +static inline int in_decimal_digit_class(int c){ 26.102 + return isdigit(c); 26.103 +} 26.104 + 26.105 +/** Determine if a character is in the hex digit class. 26.106 + * 26.107 + * @param c character to test 26.108 + * @return 1 if c is in the class, 0 otherwise. 26.109 + */ 26.110 +static inline int in_hex_digit_class(int c){ 26.111 + return isdigit(c) || in_class(c, "abcdefABCDEF"); 26.112 +} 26.113 + 26.114 + 26.115 +static inline int in_string_quote_class(int c){ 26.116 + return in_class(c, "'\""); 26.117 +} 26.118 + 26.119 +static inline int in_printable_class(int c){ 26.120 + return ('A' <= c && c <= 'Z') 26.121 + || ('a' <= c && c <= 'z') 26.122 + || ('0' <= c && c <= '9') 26.123 + || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~"); 26.124 +} 26.125 + 26.126 +extern int is_decimal_number(const char *s, int n); 26.127 +extern int is_hex_number(const char *s, int n); 26.128 +extern int is_keyword(const char *s, const char *k); 26.129 +extern int is_keychar(const char *s, char c); 26.130 + 26.131 +#endif /* !_XUTIL_LEXIS_H_ */
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/tools/libxutil/socket_stream.c Wed Nov 24 12:07:16 2004 +0000 27.3 @@ -0,0 +1,230 @@ 27.4 +/* 27.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 27.6 + * 27.7 + * This library is free software; you can redistribute it and/or modify 27.8 + * it under the terms of the GNU Lesser General Public License as published by 27.9 + * the Free Software Foundation; either version 2.1 of the License, or 27.10 + * (at your option) any later version. 27.11 + * 27.12 + * This library is distributed in the hope that it will be useful, 27.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 27.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27.15 + * GNU Lesser General Public License for more details. 27.16 + * 27.17 + * You should have received a copy of the GNU Lesser General Public License 27.18 + * along with this library; if not, write to the Free Software 27.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27.20 + */ 27.21 + 27.22 +/** @file 27.23 + * An IOStream implementation using sockets. 27.24 + */ 27.25 +#ifndef __KERNEL__ 27.26 + 27.27 +#include <stdio.h> 27.28 +#include <stdlib.h> 27.29 +#include <string.h> 27.30 +#include <unistd.h> 27.31 +#include <errno.h> 27.32 +#include "allocate.h" 27.33 +#include "socket_stream.h" 27.34 + 27.35 +#define MODULE_NAME "sock" 27.36 +#define DEBUG 0 27.37 +//#undef DEBUG 27.38 +#include "debug.h" 27.39 + 27.40 +static int socket_read(IOStream *s, void *buf, size_t n); 27.41 +static int socket_write(IOStream *s, const void *buf, size_t n); 27.42 +static int socket_error(IOStream *s); 27.43 +static int socket_close(IOStream *s); 27.44 +static void socket_free(IOStream *s); 27.45 +static int socket_flush(IOStream *s); 27.46 + 27.47 +/** Methods used by a socket IOStream. */ 27.48 +static const IOMethods socket_methods = { 27.49 + read: socket_read, 27.50 + write: socket_write, 27.51 + error: socket_error, 27.52 + close: socket_close, 27.53 + free: socket_free, 27.54 + flush: socket_flush, 27.55 +}; 27.56 + 27.57 +/** Get the socket data. 27.58 + * 27.59 + * @param io socket stream 27.60 + * @return data 27.61 + */ 27.62 +static inline SocketData * socket_data(IOStream *io){ 27.63 + return (SocketData *)io->data; 27.64 +} 27.65 + 27.66 +/** Test if a stream is a socket stream. 27.67 + * 27.68 + * @param io stream 27.69 + * @return 0 if a socket stream, -EINVAL if not 27.70 + */ 27.71 +int socket_stream_check(IOStream *io){ 27.72 + return (io && io->methods == &socket_methods ? 0 : -EINVAL); 27.73 +} 27.74 + 27.75 +/** Get the data for a socket stream. 27.76 + * 27.77 + * @param io stream 27.78 + * @param data return value for the data 27.79 + * @return 0 if a socket stream, -EINVAL if not 27.80 + */ 27.81 +int socket_stream_data(IOStream *io, SocketData **data){ 27.82 + int err = socket_stream_check(io); 27.83 + if(err){ 27.84 + *data = NULL; 27.85 + } else { 27.86 + *data = socket_data(io); 27.87 + } 27.88 + return err; 27.89 +} 27.90 + 27.91 +/** Set the destination address for a socket stream. 27.92 + * 27.93 + * @param io stream 27.94 + * @param addr address 27.95 + * @return 0 if a socket stream, -EINVAL if not 27.96 + */ 27.97 +int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){ 27.98 + int err = 0; 27.99 + SocketData *data = NULL; 27.100 + err = socket_stream_data(io, &data); 27.101 + if(!err){ 27.102 + data->daddr = *addr; 27.103 + } 27.104 + return err; 27.105 +} 27.106 + 27.107 +/** Set the send flags for a socket stream. 27.108 + * 27.109 + * @param io stream 27.110 + * @param flags flags 27.111 + * @return 0 if a socket stream, -EINVAL if not 27.112 + */ 27.113 +int socket_stream_set_flags(IOStream *io, int flags){ 27.114 + int err = 0; 27.115 + SocketData *data = NULL; 27.116 + err = socket_stream_data(io, &data); 27.117 + if(!err){ 27.118 + data->flags = flags; 27.119 + } 27.120 + return err; 27.121 +} 27.122 + 27.123 +/** Write to the underlying socket using sendto. 27.124 + * 27.125 + * @param stream input 27.126 + * @param buf where to put input 27.127 + * @param n number of bytes to write 27.128 + * @return number of bytes written 27.129 + */ 27.130 +static int socket_write(IOStream *s, const void *buf, size_t n){ 27.131 + SocketData *data = socket_data(s); 27.132 + struct sockaddr *daddr = (struct sockaddr *)&data->daddr; 27.133 + socklen_t daddr_n = sizeof(data->daddr); 27.134 + int k; 27.135 + dprintf("> sock=%d addr=%s:%d n=%d\n", 27.136 + data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n); 27.137 + if(0){ 27.138 + struct sockaddr_in self = {}; 27.139 + socklen_t self_n; 27.140 + getsockname(data->fd, (struct sockaddr *)&self, &self_n); 27.141 + dprintf("> sockname sock=%d %s:%d\n", 27.142 + data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port)); 27.143 + } 27.144 + k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n); 27.145 + dprintf("> sendto=%d\n", k); 27.146 + return k; 27.147 +} 27.148 + 27.149 +/** Read from the underlying stream using recv(); 27.150 + * 27.151 + * @param stream input 27.152 + * @param buf where to put input 27.153 + * @param n number of bytes to read 27.154 + * @return number of bytes read 27.155 + */ 27.156 +static int socket_read(IOStream *s, void *buf, size_t n){ 27.157 + SocketData *data = socket_data(s); 27.158 + int k; 27.159 + struct sockaddr *saddr = (struct sockaddr *)&data->saddr; 27.160 + socklen_t saddr_n = sizeof(data->saddr); 27.161 + k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n); 27.162 + return k; 27.163 +} 27.164 + 27.165 +/** Flush the socket (no-op). 27.166 + * 27.167 + * @param s socket stream 27.168 + * @return 0 on success, error code otherwise 27.169 + */ 27.170 +static int socket_flush(IOStream *s){ 27.171 + return 0; 27.172 +} 27.173 + 27.174 +/** Check if a socket stream has an error (no-op). 27.175 + * 27.176 + * @param s socket stream 27.177 + * @return 1 if has an error, 0 otherwise 27.178 + */ 27.179 +static int socket_error(IOStream *s){ 27.180 + // Read SOL_SOCKET/SO_ERROR ? 27.181 + return 0; 27.182 +} 27.183 + 27.184 +/** Close a socket stream. 27.185 + * 27.186 + * @param s socket stream to close 27.187 + * @return result of the close 27.188 + */ 27.189 +static int socket_close(IOStream *s){ 27.190 + SocketData *data = socket_data(s); 27.191 + return close(data->fd); 27.192 +} 27.193 + 27.194 +/** Free a socket stream. 27.195 + * 27.196 + * @param s socket stream 27.197 + */ 27.198 +static void socket_free(IOStream *s){ 27.199 + SocketData *data = socket_data(s); 27.200 + deallocate(data); 27.201 +} 27.202 + 27.203 +/** Create an IOStream for a socket. 27.204 + * 27.205 + * @param fd socket to wtap 27.206 + * @return new IOStream using fd for i/o 27.207 + */ 27.208 +IOStream *socket_stream_new(int fd){ 27.209 + int err = -ENOMEM; 27.210 + IOStream *io = NULL; 27.211 + SocketData *data = NULL; 27.212 + 27.213 + io = ALLOCATE(IOStream); 27.214 + if(!io) goto exit; 27.215 + io->methods = &socket_methods; 27.216 + data = ALLOCATE(SocketData); 27.217 + if(!data) goto exit; 27.218 + io->data = data; 27.219 + data->fd = fd; 27.220 + data->buf_n = sizeof(data->buf); 27.221 + err = 0; 27.222 + exit: 27.223 + if(err){ 27.224 + if(io){ 27.225 + if(data) deallocate(data); 27.226 + deallocate(io); 27.227 + io = NULL; 27.228 + } 27.229 + } 27.230 + return io; 27.231 +} 27.232 + 27.233 +#endif
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/tools/libxutil/socket_stream.h Wed Nov 24 12:07:16 2004 +0000 28.3 @@ -0,0 +1,53 @@ 28.4 +/* 28.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 28.6 + * 28.7 + * This library is free software; you can redistribute it and/or modify 28.8 + * it under the terms of the GNU Lesser General Public License as published by 28.9 + * the Free Software Foundation; either version 2.1 of the License, or 28.10 + * (at your option) any later version. 28.11 + * 28.12 + * This library is distributed in the hope that it will be useful, 28.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 28.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28.15 + * GNU Lesser General Public License for more details. 28.16 + * 28.17 + * You should have received a copy of the GNU Lesser General Public License 28.18 + * along with this library; if not, write to the Free Software 28.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28.20 + */ 28.21 + 28.22 +#ifndef _XEN_LIB_SOCKET_STREAM_H_ 28.23 +#define _XEN_LIB_SOCKET_STREAM_H_ 28.24 + 28.25 +#ifndef __KERNEL__ 28.26 +#include "iostream.h" 28.27 +#include <stdio.h> 28.28 + 28.29 +#include <sys/socket.h> 28.30 +#include <netinet/in.h> 28.31 +#include <arpa/inet.h> 28.32 + 28.33 +/** Data associated with a socket stream. */ 28.34 +typedef struct SocketData { 28.35 + /** The socket file descriptor. */ 28.36 + int fd; 28.37 + /** Source address from last read (recvfrom). */ 28.38 + struct sockaddr_in saddr; 28.39 + /** Destination address for writes (sendto). */ 28.40 + struct sockaddr_in daddr; 28.41 + /** Write flags (sendto). */ 28.42 + int flags; 28.43 + /** Buffer size. */ 28.44 + int buf_n; 28.45 + /** Buffer for formatted printing. */ 28.46 + char buf[1024]; 28.47 +} SocketData; 28.48 + 28.49 +extern IOStream *socket_stream_new(int fd); 28.50 +extern int socket_stream_data(IOStream *io, SocketData **data); 28.51 +extern int socket_stream_check(IOStream *io); 28.52 +extern int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr); 28.53 +extern int socket_stream_set_flags(IOStream *io, int flags); 28.54 + 28.55 +#endif 28.56 +#endif /* !_XEN_LIB_SOCKET_STREAM_H_ */
29.1 --- a/tools/libxutil/string_stream.c Wed Nov 24 11:51:49 2004 +0000 29.2 +++ b/tools/libxutil/string_stream.c Wed Nov 24 12:07:16 2004 +0000 29.3 @@ -1,5 +1,5 @@ 29.4 /* 29.5 - * Copyright (C) 2001, 2002 Hewlett-Packard Company. 29.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 29.7 * 29.8 * This library is free software; you can redistribute it and/or modify 29.9 * it under the terms of the GNU Lesser General Public License as published by
30.1 --- a/tools/libxutil/string_stream.h Wed Nov 24 11:51:49 2004 +0000 30.2 +++ b/tools/libxutil/string_stream.h Wed Nov 24 12:07:16 2004 +0000 30.3 @@ -1,5 +1,5 @@ 30.4 /* 30.5 - * Copyright (C) 2001, 2002 Hewlett-Packard Company. 30.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 30.7 * 30.8 * This library is free software; you can redistribute it and/or modify 30.9 * it under the terms of the GNU Lesser General Public License as published by
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/tools/libxutil/sxpr.c Wed Nov 24 12:07:16 2004 +0000 31.3 @@ -0,0 +1,956 @@ 31.4 +/* 31.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 31.6 + * 31.7 + * This library is free software; you can redistribute it and/or modify 31.8 + * it under the terms of the GNU Lesser General Public License as 31.9 + * published by the Free Software Foundation; either version 2.1 of the 31.10 + * License, or (at your option) any later version. This library is 31.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 31.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 31.13 + * FITNESS FOR A PARTICULAR PURPOSE. 31.14 + * See the GNU Lesser General Public License for more details. 31.15 + * 31.16 + * You should have received a copy of the GNU Lesser General Public License 31.17 + * along with this library; if not, write to the Free Software Foundation, 31.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 31.19 + */ 31.20 + 31.21 +#include <stdarg.h> 31.22 +#include "sys_string.h" 31.23 +#include "lexis.h" 31.24 +#include "sys_net.h" 31.25 +#include "hash_table.h" 31.26 +#include "sxpr.h" 31.27 + 31.28 +#ifdef __KERNEL__ 31.29 +#include <linux/errno.h> 31.30 +#else 31.31 +#include <errno.h> 31.32 +#endif 31.33 + 31.34 +#undef free 31.35 + 31.36 +/** @file 31.37 + * General representation of sxprs. 31.38 + * Includes print, equal, and free functions for the sxpr types. 31.39 + * 31.40 + * Zero memory containing an Sxpr will have the value ONONE - this is intentional. 31.41 + * When a function returning an sxpr cannot allocate memory we return ONOMEM. 31.42 + * 31.43 + */ 31.44 + 31.45 +static int atom_print(IOStream *io, Sxpr obj, unsigned flags); 31.46 +static int atom_equal(Sxpr x, Sxpr y); 31.47 +static void atom_free(Sxpr obj); 31.48 + 31.49 +static int string_print(IOStream *io, Sxpr obj, unsigned flags); 31.50 +static int string_equal(Sxpr x, Sxpr y); 31.51 +static void string_free(Sxpr obj); 31.52 + 31.53 +static int cons_print(IOStream *io, Sxpr obj, unsigned flags); 31.54 +static int cons_equal(Sxpr x, Sxpr y); 31.55 +static void cons_free(Sxpr obj); 31.56 + 31.57 +static int null_print(IOStream *io, Sxpr obj, unsigned flags); 31.58 +static int none_print(IOStream *io, Sxpr obj, unsigned flags); 31.59 +static int int_print(IOStream *io, Sxpr obj, unsigned flags); 31.60 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags); 31.61 + 31.62 +/** Type definitions. */ 31.63 +static SxprType types[1024] = { 31.64 + [T_NONE] { type: T_NONE, name: "none", print: none_print }, 31.65 + [T_NULL] { type: T_NULL, name: "null", print: null_print }, 31.66 + [T_UINT] { type: T_UINT, name: "int", print: int_print, }, 31.67 + [T_BOOL] { type: T_BOOL, name: "bool", print: bool_print, }, 31.68 + [T_ATOM] { type: T_ATOM, name: "atom", print: atom_print, 31.69 + pointer: TRUE, 31.70 + free: atom_free, 31.71 + equal: atom_equal, 31.72 + }, 31.73 + [T_STRING] { type: T_STRING, name: "string", print: string_print, 31.74 + pointer: TRUE, 31.75 + free: string_free, 31.76 + equal: string_equal, 31.77 + }, 31.78 + [T_CONS] { type: T_CONS, name: "cons", print: cons_print, 31.79 + pointer: TRUE, 31.80 + free: cons_free, 31.81 + equal: cons_equal, 31.82 + }, 31.83 +}; 31.84 + 31.85 +/** Number of entries in the types array. */ 31.86 +static int type_sup = sizeof(types)/sizeof(types[0]); 31.87 + 31.88 +/** Get the type definition for a given type code. 31.89 + * 31.90 + * @param ty type code 31.91 + * @return type definition or null 31.92 + */ 31.93 +SxprType *get_sxpr_type(int ty){ 31.94 + if(0 <= ty && ty < type_sup){ 31.95 + return types+ty; 31.96 + } 31.97 + return NULL; 31.98 +} 31.99 + 31.100 +/** The default print function. 31.101 + * 31.102 + * @param io stream to print to 31.103 + * @param x sxpr to print 31.104 + * @param flags print flags 31.105 + * @return number of bytes written on success 31.106 + */ 31.107 +int default_print(IOStream *io, Sxpr x, unsigned flags){ 31.108 + return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x)); 31.109 +} 31.110 + 31.111 +/** The default equal function. 31.112 + * Uses eq(). 31.113 + * 31.114 + * @param x sxpr to compare 31.115 + * @param y sxpr to compare 31.116 + * @return 1 if equal, 0 otherwise 31.117 + */ 31.118 +int default_equal(Sxpr x, Sxpr y){ 31.119 + return eq(x, y); 31.120 +} 31.121 + 31.122 +/** General sxpr print function. 31.123 + * Prints an sxpr on a stream using the print function for the sxpr type. 31.124 + * Printing is controlled by flags from the PrintFlags enum. 31.125 + * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr 31.126 + * (for debugging). 31.127 + * 31.128 + * @param io stream to print to 31.129 + * @param x sxpr to print 31.130 + * @param flags print flags 31.131 + * @return number of bytes written 31.132 + */ 31.133 +int objprint(IOStream *io, Sxpr x, unsigned flags){ 31.134 + SxprType *def = get_sxpr_type(get_type(x)); 31.135 + ObjPrintFn *print_fn = (def && def->print ? def->print : default_print); 31.136 + int k = 0; 31.137 + if(!io) return k; 31.138 + if(flags & PRINT_TYPE){ 31.139 + k += IOStream_print(io, "%s:", def->name); 31.140 + } 31.141 + k += print_fn(io, x, flags); 31.142 + return k; 31.143 +} 31.144 + 31.145 +/** General sxpr free function. 31.146 + * Frees an sxpr using the free function for its type. 31.147 + * Free functions must recursively free any subsxprs. 31.148 + * If no function is defined then the default is to 31.149 + * free sxprs whose type has pointer true. 31.150 + * Sxprs must not be used after freeing. 31.151 + * 31.152 + * @param x sxpr to free 31.153 + */ 31.154 +void objfree(Sxpr x){ 31.155 + SxprType *def = get_sxpr_type(get_type(x)); 31.156 + 31.157 + if(def){ 31.158 + if(def->free){ 31.159 + def->free(x); 31.160 + } else if (def->pointer){ 31.161 + hfree(x); 31.162 + } 31.163 + } 31.164 +} 31.165 + 31.166 +/** General sxpr equality function. 31.167 + * Compares x and y using the equal function for x. 31.168 + * Uses default_equal() if x has no equal function. 31.169 + * 31.170 + * @param x sxpr to compare 31.171 + * @param y sxpr to compare 31.172 + * @return 1 if equal, 0 otherwise 31.173 + */ 31.174 +int objequal(Sxpr x, Sxpr y){ 31.175 + SxprType *def = get_sxpr_type(get_type(x)); 31.176 + ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal); 31.177 + return equal_fn(x, y); 31.178 +} 31.179 + 31.180 +/** Search for a key in an alist. 31.181 + * An alist is a list of conses, where the cars 31.182 + * of the conses are the keys. Compares keys using equality. 31.183 + * 31.184 + * @param k key 31.185 + * @param l alist to search 31.186 + * @return first element of l with car k, or ONULL 31.187 + */ 31.188 +Sxpr assoc(Sxpr k, Sxpr l){ 31.189 + for( ; CONSP(l) ; l = CDR(l)){ 31.190 + Sxpr x = CAR(l); 31.191 + if(CONSP(x) && objequal(k, CAR(x))){ 31.192 + return x; 31.193 + } 31.194 + } 31.195 + return ONULL; 31.196 +} 31.197 + 31.198 +/** Search for a key in an alist. 31.199 + * An alist is a list of conses, where the cars 31.200 + * of the conses are the keys. Compares keys using eq. 31.201 + * 31.202 + * @param k key 31.203 + * @param l alist to search 31.204 + * @return first element of l with car k, or ONULL 31.205 + */ 31.206 +Sxpr assocq(Sxpr k, Sxpr l){ 31.207 + for( ; CONSP(l); l = CDR(l)){ 31.208 + Sxpr x = CAR(l); 31.209 + if(CONSP(x) && eq(k, CAR(x))){ 31.210 + return x; 31.211 + } 31.212 + } 31.213 + return ONULL; 31.214 +} 31.215 + 31.216 +/** Add a new key and value to an alist. 31.217 + * 31.218 + * @param k key 31.219 + * @param l value 31.220 + * @param l alist 31.221 + * @return l with the new cell added to the front 31.222 + */ 31.223 +Sxpr acons(Sxpr k, Sxpr v, Sxpr l){ 31.224 + Sxpr x, y; 31.225 + x = cons_new(k, v); 31.226 + if(NOMEMP(x)) return x; 31.227 + y = cons_new(x, l); 31.228 + if(NOMEMP(y)) cons_free_cells(x); 31.229 + return y; 31.230 +} 31.231 + 31.232 +/** Test if a list contains an element. 31.233 + * Uses sxpr equality. 31.234 + * 31.235 + * @param l list 31.236 + * @param x element to look for 31.237 + * @return a tail of l with x as car, or ONULL 31.238 + */ 31.239 +Sxpr cons_member(Sxpr l, Sxpr x){ 31.240 + for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){} 31.241 + return l; 31.242 +} 31.243 + 31.244 +/** Test if a list contains an element satisfying a test. 31.245 + * The test function is called with v and an element of the list. 31.246 + * 31.247 + * @param l list 31.248 + * @param test_fn test function to use 31.249 + * @param v value for first argument to the test 31.250 + * @return a tail of l with car satisfying the test, or 0 31.251 + */ 31.252 +Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){ 31.253 + for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ } 31.254 + return l; 31.255 +} 31.256 + 31.257 +/** Test if the elements of list 't' are a subset of the elements 31.258 + * of list 's'. Element order is not significant. 31.259 + * 31.260 + * @param s element list to check subset of 31.261 + * @param t element list to check if is a subset 31.262 + * @return 1 if is a subset, 0 otherwise 31.263 + */ 31.264 +int cons_subset(Sxpr s, Sxpr t){ 31.265 + for( ; CONSP(t); t = CDR(t)){ 31.266 + if(!CONSP(cons_member(s, CAR(t)))){ 31.267 + return 0; 31.268 + } 31.269 + } 31.270 + return 1; 31.271 +} 31.272 + 31.273 +/** Test if two lists have equal sets of elements. 31.274 + * Element order is not significant. 31.275 + * 31.276 + * @param s list to check 31.277 + * @param t list to check 31.278 + * @return 1 if equal, 0 otherwise 31.279 + */ 31.280 +int cons_set_equal(Sxpr s, Sxpr t){ 31.281 + return cons_subset(s, t) && cons_subset(t, s); 31.282 +} 31.283 + 31.284 +#ifdef USE_GC 31.285 +/*============================================================================*/ 31.286 +/* The functions inside this ifdef are only safe if GC is used. 31.287 + * Otherwise they may leak memory. 31.288 + */ 31.289 + 31.290 +/** Remove an element from a list (GC only). 31.291 + * Uses sxpr equality and removes all instances, even 31.292 + * if there are more than one. 31.293 + * 31.294 + * @param l list to remove elements from 31.295 + * @param x element to remove 31.296 + * @return modified input list 31.297 + */ 31.298 +Sxpr cons_remove(Sxpr l, Sxpr x){ 31.299 + return cons_remove_if(l, eq, x); 31.300 +} 31.301 + 31.302 +/** Remove elements satisfying a test (GC only). 31.303 + * The test function is called with v and an element of the set. 31.304 + * 31.305 + * @param l list to remove elements from 31.306 + * @param test_fn function to use to decide if an element should be removed 31.307 + * @return modified input list 31.308 + */ 31.309 +Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){ 31.310 + Sxpr prev = ONULL, elt, next; 31.311 + 31.312 + for(elt = l; CONSP(elt); elt = next){ 31.313 + next = CDR(elt); 31.314 + if(test_fn(v, CAR(elt))){ 31.315 + if(NULLP(prev)){ 31.316 + l = next; 31.317 + } else { 31.318 + CDR(prev) = next; 31.319 + } 31.320 + } 31.321 + } 31.322 + return l; 31.323 +} 31.324 + 31.325 +/** Set the value for a key in an alist (GC only). 31.326 + * If the key is present, changes the value, otherwise 31.327 + * adds a new cell. 31.328 + * 31.329 + * @param k key 31.330 + * @param v value 31.331 + * @param l alist 31.332 + * @return modified or extended list 31.333 + */ 31.334 +Sxpr setf(Sxpr k, Sxpr v, Sxpr l){ 31.335 + Sxpr e = assoc(k, l); 31.336 + if(NULLP(e)){ 31.337 + l = acons(k, v, l); 31.338 + } else { 31.339 + CAR(CDR(e)) = v; 31.340 + } 31.341 + return l; 31.342 +} 31.343 +/*============================================================================*/ 31.344 +#endif /* USE_GC */ 31.345 + 31.346 +/** Create a new atom with the given name. 31.347 + * 31.348 + * @param name the name 31.349 + * @return new atom 31.350 + */ 31.351 +Sxpr atom_new(char *name){ 31.352 + Sxpr n, obj = ONOMEM; 31.353 + 31.354 + n = string_new(name); 31.355 + if(NOMEMP(n)) goto exit; 31.356 + obj = HALLOC(ObjAtom, T_ATOM); 31.357 + if(NOMEMP(obj)) goto exit; 31.358 + OBJ_ATOM(obj)->name = n; 31.359 + exit: 31.360 + return obj; 31.361 +} 31.362 + 31.363 +/** Free an atom. 31.364 + * 31.365 + * @param obj to free 31.366 + */ 31.367 +void atom_free(Sxpr obj){ 31.368 + // Interned atoms are shared, so do not free. 31.369 + if(OBJ_ATOM(obj)->interned) return; 31.370 + objfree(OBJ_ATOM(obj)->name); 31.371 + hfree(obj); 31.372 +} 31.373 + 31.374 +/** Print an atom. Prints the atom name. 31.375 + * 31.376 + * @param io stream to print to 31.377 + * @param obj to print 31.378 + * @param flags print flags 31.379 + * @return number of bytes printed 31.380 + */ 31.381 +int atom_print(IOStream *io, Sxpr obj, unsigned flags){ 31.382 + //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW)); 31.383 + return string_print(io, OBJ_ATOM(obj)->name, flags); 31.384 +} 31.385 + 31.386 +/** Atom equality. 31.387 + * 31.388 + * @param x to compare 31.389 + * @param y to compare 31.390 + * @return 1 if equal, 0 otherwise 31.391 + */ 31.392 +int atom_equal(Sxpr x, Sxpr y){ 31.393 + int ok; 31.394 + ok = eq(x, y); 31.395 + if(ok) goto exit; 31.396 + ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name); 31.397 + if(ok) goto exit; 31.398 + ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y); 31.399 + exit: 31.400 + return ok; 31.401 +} 31.402 + 31.403 +/** Get the name of an atom. 31.404 + * 31.405 + * @param obj atom 31.406 + * @return name 31.407 + */ 31.408 +char * atom_name(Sxpr obj){ 31.409 + return string_string(OBJ_ATOM(obj)->name); 31.410 +} 31.411 + 31.412 +/** Get the C string from a string sxpr. 31.413 + * 31.414 + * @param obj string sxpr 31.415 + * @return string 31.416 + */ 31.417 +char * string_string(Sxpr obj){ 31.418 + return OBJ_STRING(obj); 31.419 +} 31.420 + 31.421 +/** Get the length of a string. 31.422 + * 31.423 + * @param obj string 31.424 + * @return length 31.425 + */ 31.426 +int string_length(Sxpr obj){ 31.427 + return strlen(OBJ_STRING(obj)); 31.428 +} 31.429 + 31.430 +/** Create a new string. The input string is copied, 31.431 + * and must be null-terminated. 31.432 + * 31.433 + * @param s characters to put in the string 31.434 + * @return new sxpr 31.435 + */ 31.436 +Sxpr string_new(char *s){ 31.437 + int n = (s ? strlen(s) : 0); 31.438 + Sxpr obj; 31.439 + obj = halloc(n+1, T_STRING); 31.440 + if(!NOMEMP(obj)){ 31.441 + char *str = OBJ_STRING(obj); 31.442 + strncpy(str, s, n); 31.443 + str[n] = '\0'; 31.444 + } 31.445 + return obj; 31.446 +} 31.447 + 31.448 +/** Free a string. 31.449 + * 31.450 + * @param obj to free 31.451 + */ 31.452 +void string_free(Sxpr obj){ 31.453 + hfree(obj); 31.454 +} 31.455 + 31.456 +/** Determine if a string needs escapes when printed 31.457 + * using the given flags. 31.458 + * 31.459 + * @param str string to check 31.460 + * @param flags print flags 31.461 + * @return 1 if needs escapes, 0 otherwise 31.462 + */ 31.463 +int needs_escapes(char *str, unsigned flags){ 31.464 + char *c; 31.465 + int val = 0; 31.466 + 31.467 + if(str){ 31.468 + for(c=str; *c; c++){ 31.469 + if(in_alpha_class(*c)) continue; 31.470 + if(in_decimal_digit_class(*c)) continue; 31.471 + if(in_class(*c, "/._+:@~-")) continue; 31.472 + val = 1; 31.473 + break; 31.474 + } 31.475 + } 31.476 + //printf("\n> val=%d str=|%s|\n", val, str); 31.477 + return val; 31.478 +} 31.479 + 31.480 +/** Print a string to a stream, with escapes if necessary. 31.481 + * 31.482 + * @param io stream to print to 31.483 + * @param str string 31.484 + * @param flags print flags 31.485 + * @return number of bytes written 31.486 + */ 31.487 +int _string_print(IOStream *io, char *str, unsigned flags){ 31.488 + int k = 0; 31.489 + if((flags & PRINT_RAW) || !needs_escapes(str, flags)){ 31.490 + k += IOStream_print(io, str); 31.491 + } else { 31.492 + k += IOStream_print(io, "\""); 31.493 + if(str){ 31.494 + char *s; 31.495 + for(s = str; *s; s++){ 31.496 + if(*s < ' ' || *s >= 127 ){ 31.497 + switch(*s){ 31.498 + case '\a': k += IOStream_print(io, "\\a"); break; 31.499 + case '\b': k += IOStream_print(io, "\\b"); break; 31.500 + case '\f': k += IOStream_print(io, "\\f"); break; 31.501 + case '\n': k += IOStream_print(io, "\\n"); break; 31.502 + case '\r': k += IOStream_print(io, "\\r"); break; 31.503 + case '\t': k += IOStream_print(io, "\\t"); break; 31.504 + case '\v': k += IOStream_print(io, "\\v"); break; 31.505 + default: 31.506 + // Octal escape; 31.507 + k += IOStream_print(io, "\\%o", *s); 31.508 + break; 31.509 + } 31.510 + } else if(*s == c_double_quote || 31.511 + *s == c_single_quote || 31.512 + *s == c_escape){ 31.513 + k += IOStream_print(io, "\\%c", *s); 31.514 + } else { 31.515 + k+= IOStream_print(io, "%c", *s); 31.516 + } 31.517 + } 31.518 + } 31.519 + k += IOStream_print(io, "\""); 31.520 + } 31.521 + return k; 31.522 +} 31.523 + 31.524 +/** Print a string to a stream, with escapes if necessary. 31.525 + * 31.526 + * @param io stream to print to 31.527 + * @param obj string 31.528 + * @param flags print flags 31.529 + * @return number of bytes written 31.530 + */ 31.531 +int string_print(IOStream *io, Sxpr obj, unsigned flags){ 31.532 + return _string_print(io, OBJ_STRING(obj), flags); 31.533 +} 31.534 + 31.535 +/** Compare an sxpr with a string for equality. 31.536 + * 31.537 + * @param x string to compare with 31.538 + * @param y sxpr to compare 31.539 + * @return 1 if equal, 0 otherwise 31.540 + */ 31.541 +int string_equal(Sxpr x, Sxpr y){ 31.542 + int ok = 0; 31.543 + ok = eq(x,y); 31.544 + if(ok) goto exit; 31.545 + ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y)); 31.546 + if(ok) goto exit; 31.547 + ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y)); 31.548 + exit: 31.549 + return ok; 31.550 +} 31.551 + 31.552 +/** Create a new cons cell. 31.553 + * The cell is ONOMEM if either argument is. 31.554 + * 31.555 + * @param car sxpr for the car 31.556 + * @param cdr sxpr for the cdr 31.557 + * @return new cons 31.558 + */ 31.559 +Sxpr cons_new(Sxpr car, Sxpr cdr){ 31.560 + Sxpr obj; 31.561 + if(NOMEMP(car) || NOMEMP(cdr)){ 31.562 + obj = ONOMEM; 31.563 + } else { 31.564 + obj = HALLOC(ObjCons, T_CONS); 31.565 + if(!NOMEMP(obj)){ 31.566 + ObjCons *z = OBJ_CONS(obj); 31.567 + z->car = car; 31.568 + z->cdr = cdr; 31.569 + } 31.570 + } 31.571 + return obj; 31.572 +} 31.573 + 31.574 +/** Push a new element onto a list. 31.575 + * 31.576 + * @param list list to add to 31.577 + * @param elt element to add 31.578 + * @return 0 if successful, error code otherwise 31.579 + */ 31.580 +int cons_push(Sxpr *list, Sxpr elt){ 31.581 + Sxpr l; 31.582 + l = cons_new(elt, *list); 31.583 + if(NOMEMP(l)) return -ENOMEM; 31.584 + *list = l; 31.585 + return 0; 31.586 +} 31.587 + 31.588 +/** Free a cons. Recursively frees the car and cdr. 31.589 + * 31.590 + * @param obj to free 31.591 + */ 31.592 +void cons_free(Sxpr obj){ 31.593 + Sxpr next; 31.594 + for(; CONSP(obj); obj = next){ 31.595 + next = CDR(obj); 31.596 + objfree(CAR(obj)); 31.597 + hfree(obj); 31.598 + } 31.599 + if(!NULLP(obj)){ 31.600 + objfree(obj); 31.601 + } 31.602 +} 31.603 + 31.604 +/** Free a cons and its cdr cells, but not the car sxprs. 31.605 + * Does nothing if called on something that is not a cons. 31.606 + * 31.607 + * @param obj to free 31.608 + */ 31.609 +void cons_free_cells(Sxpr obj){ 31.610 + Sxpr next; 31.611 + for(; CONSP(obj); obj = next){ 31.612 + next = CDR(obj); 31.613 + hfree(obj); 31.614 + } 31.615 +} 31.616 + 31.617 +/** Print a cons. 31.618 + * Prints the cons in list format if the cdrs are conses. 31.619 + * uses pair (dot) format if the last cdr is not a cons (or null). 31.620 + * 31.621 + * @param io stream to print to 31.622 + * @param obj to print 31.623 + * @param flags print flags 31.624 + * @return number of bytes written 31.625 + */ 31.626 +int cons_print(IOStream *io, Sxpr obj, unsigned flags){ 31.627 + int first = 1; 31.628 + int k = 0; 31.629 + k += IOStream_print(io, "("); 31.630 + for( ; CONSP(obj) ; obj = CDR(obj)){ 31.631 + if(first){ 31.632 + first = 0; 31.633 + } else { 31.634 + k += IOStream_print(io, " "); 31.635 + } 31.636 + k += objprint(io, CAR(obj), flags); 31.637 + } 31.638 + if(!NULLP(obj)){ 31.639 + k += IOStream_print(io, " . "); 31.640 + k += objprint(io, obj, flags); 31.641 + } 31.642 + k += IOStream_print(io, ")"); 31.643 + return (IOStream_error(io) ? -1 : k); 31.644 +} 31.645 + 31.646 +/** Compare a cons with another sxpr for equality. 31.647 + * If y is a cons, compares the cars and cdrs recursively. 31.648 + * 31.649 + * @param x cons to compare 31.650 + * @param y sxpr to compare 31.651 + * @return 1 if equal, 0 otherwise 31.652 + */ 31.653 +int cons_equal(Sxpr x, Sxpr y){ 31.654 + return CONSP(y) && 31.655 + objequal(CAR(x), CAR(y)) && 31.656 + objequal(CDR(x), CDR(y)); 31.657 +} 31.658 + 31.659 +/** Return the length of a cons list. 31.660 + * 31.661 + * @param obj list 31.662 + * @return length 31.663 + */ 31.664 +int cons_length(Sxpr obj){ 31.665 + int count = 0; 31.666 + for( ; CONSP(obj); obj = CDR(obj)){ 31.667 + count++; 31.668 + } 31.669 + return count; 31.670 +} 31.671 + 31.672 +/** Destructively reverse a cons list in-place. 31.673 + * If the argument is not a cons it is returned unchanged. 31.674 + * 31.675 + * @param l to reverse 31.676 + * @return reversed list 31.677 + */ 31.678 +Sxpr nrev(Sxpr l){ 31.679 + if(CONSP(l)){ 31.680 + // Iterate down the cells in the list making the cdr of 31.681 + // each cell point to the previous cell. The last cell 31.682 + // is the head of the reversed list. 31.683 + Sxpr prev = ONULL; 31.684 + Sxpr cell = l; 31.685 + Sxpr next; 31.686 + 31.687 + while(1){ 31.688 + next = CDR(cell); 31.689 + CDR(cell) = prev; 31.690 + if(!CONSP(next)) break; 31.691 + prev = cell; 31.692 + cell = next; 31.693 + } 31.694 + l = cell; 31.695 + } 31.696 + return l; 31.697 +} 31.698 + 31.699 +/** Print the null sxpr. 31.700 + * 31.701 + * @param io stream to print to 31.702 + * @param obj to print 31.703 + * @param flags print flags 31.704 + * @return number of bytes written 31.705 + */ 31.706 +static int null_print(IOStream *io, Sxpr obj, unsigned flags){ 31.707 + return IOStream_print(io, "()"); 31.708 +} 31.709 + 31.710 +/** Print the `unspecified' sxpr none. 31.711 + * 31.712 + * @param io stream to print to 31.713 + * @param obj to print 31.714 + * @param flags print flags 31.715 + * @return number of bytes written 31.716 + */ 31.717 +static int none_print(IOStream *io, Sxpr obj, unsigned flags){ 31.718 + return IOStream_print(io, "<none>"); 31.719 +} 31.720 + 31.721 +/** Print an integer. 31.722 + * 31.723 + * @param io stream to print to 31.724 + * @param obj to print 31.725 + * @param flags print flags 31.726 + * @return number of bytes written 31.727 + */ 31.728 +static int int_print(IOStream *io, Sxpr obj, unsigned flags){ 31.729 + return IOStream_print(io, "%d", OBJ_INT(obj)); 31.730 +} 31.731 + 31.732 +/** Print a boolean. 31.733 + * 31.734 + * @param io stream to print to 31.735 + * @param obj to print 31.736 + * @param flags print flags 31.737 + * @return number of bytes written 31.738 + */ 31.739 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags){ 31.740 + return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false)); 31.741 +} 31.742 + 31.743 +int sxprp(Sxpr obj, Sxpr name){ 31.744 + return CONSP(obj) && objequal(CAR(obj), name); 31.745 +} 31.746 + 31.747 +/** Get the name of an element. 31.748 + * 31.749 + * @param obj element 31.750 + * @return name 31.751 + */ 31.752 +Sxpr sxpr_name(Sxpr obj){ 31.753 + Sxpr val = ONONE; 31.754 + if(CONSP(obj)){ 31.755 + val = CAR(obj); 31.756 + } else if(STRINGP(obj) || ATOMP(obj)){ 31.757 + val = obj; 31.758 + } 31.759 + return val; 31.760 +} 31.761 + 31.762 +int sxpr_is(Sxpr obj, char *s){ 31.763 + if(ATOMP(obj)) return !strcmp(atom_name(obj), s); 31.764 + if(STRINGP(obj)) return !strcmp(string_string(obj), s); 31.765 + return 0; 31.766 +} 31.767 + 31.768 +int sxpr_elementp(Sxpr obj, Sxpr name){ 31.769 + int ok = 0; 31.770 + ok = CONSP(obj) && objequal(CAR(obj), name); 31.771 + return ok; 31.772 +} 31.773 + 31.774 +/** Get the attributes of an sxpr. 31.775 + * 31.776 + * @param obj sxpr 31.777 + * @return attributes 31.778 + */ 31.779 +Sxpr sxpr_attributes(Sxpr obj){ 31.780 + Sxpr val = ONULL; 31.781 + if(CONSP(obj)){ 31.782 + obj = CDR(obj); 31.783 + if(CONSP(obj)){ 31.784 + obj = CAR(obj); 31.785 + if(sxprp(obj, intern("@"))){ 31.786 + val = CDR(obj); 31.787 + } 31.788 + } 31.789 + } 31.790 + return val; 31.791 +} 31.792 + 31.793 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){ 31.794 + Sxpr val = ONONE; 31.795 + val = assoc(sxpr_attributes(obj), key); 31.796 + if(CONSP(val) && CONSP(CDR(val))){ 31.797 + val = CADR(def); 31.798 + } else { 31.799 + val = def; 31.800 + } 31.801 + return val; 31.802 +} 31.803 + 31.804 +/** Get the children of an sxpr. 31.805 + * 31.806 + * @param obj sxpr 31.807 + * @return children 31.808 + */ 31.809 +Sxpr sxpr_children(Sxpr obj){ 31.810 + Sxpr val = ONULL; 31.811 + if(CONSP(obj)){ 31.812 + val = CDR(obj); 31.813 + if(CONSP(val) && sxprp(CAR(val), intern("@"))){ 31.814 + val = CDR(val); 31.815 + } 31.816 + } 31.817 + return val; 31.818 +} 31.819 + 31.820 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){ 31.821 + Sxpr val = ONONE; 31.822 + Sxpr l; 31.823 + for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){ 31.824 + if(sxprp(CAR(l), name)){ 31.825 + val = CAR(l); 31.826 + break; 31.827 + } 31.828 + } 31.829 + if(NONEP(val)) val = def; 31.830 + return val; 31.831 +} 31.832 + 31.833 +Sxpr sxpr_child0(Sxpr obj, Sxpr def){ 31.834 + Sxpr val = ONONE; 31.835 + Sxpr l = sxpr_children(obj); 31.836 + if(CONSP(l)){ 31.837 + val = CAR(l); 31.838 + } else { 31.839 + val = def; 31.840 + } 31.841 + return val; 31.842 +} 31.843 + 31.844 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def){ 31.845 + Sxpr val = def; 31.846 + Sxpr l; 31.847 + int i; 31.848 + for (i = 0, l = sxpr_children(obj); CONSP(l); i++, l = CDR(l)){ 31.849 + if(i == n){ 31.850 + val = CAR(l); 31.851 + break; 31.852 + } 31.853 + } 31.854 + return val; 31.855 +} 31.856 + 31.857 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){ 31.858 + Sxpr val = ONONE; 31.859 + val = sxpr_child(obj, name, ONONE); 31.860 + if(NONEP(val)){ 31.861 + val = def; 31.862 + } else { 31.863 + val = sxpr_child0(val, def); 31.864 + } 31.865 + return val; 31.866 +} 31.867 + 31.868 +/** Table of interned symbols. Indexed by symbol name. */ 31.869 +static HashTable *symbols = NULL; 31.870 + 31.871 +/** Hash function for entries in the symbol table. 31.872 + * 31.873 + * @param key to hash 31.874 + * @return hashcode 31.875 + */ 31.876 +static Hashcode sym_hash_fn(void *key){ 31.877 + return hash_string((char*)key); 31.878 +} 31.879 + 31.880 +/** Key equality function for the symbol table. 31.881 + * 31.882 + * @param x to compare 31.883 + * @param y to compare 31.884 + * @return 1 if equal, 0 otherwise 31.885 + */ 31.886 +static int sym_equal_fn(void *x, void *y){ 31.887 + return !strcmp((char*)x, (char*)y); 31.888 +} 31.889 + 31.890 +/** Entry free function for the symbol table. 31.891 + * 31.892 + * @param table the entry is in 31.893 + * @param entry being freed 31.894 + */ 31.895 +static void sym_free_fn(HashTable *table, HTEntry *entry){ 31.896 + if(entry){ 31.897 + objfree(((ObjAtom*)entry->value)->name); 31.898 + HTEntry_free(entry); 31.899 + } 31.900 +} 31.901 + 31.902 +/** Initialize the symbol table. 31.903 + * 31.904 + * @return 0 on sucess, error code otherwise 31.905 + */ 31.906 +static int init_symbols(void){ 31.907 + symbols = HashTable_new(100); 31.908 + if(symbols){ 31.909 + symbols->key_hash_fn = sym_hash_fn; 31.910 + symbols->key_equal_fn = sym_equal_fn; 31.911 + symbols->entry_free_fn = sym_free_fn; 31.912 + return 0; 31.913 + } 31.914 + return -1; 31.915 +} 31.916 + 31.917 +/** Cleanup the symbol table. Frees the table and all its symbols. 31.918 + */ 31.919 +void cleanup_symbols(void){ 31.920 + HashTable_free(symbols); 31.921 + symbols = NULL; 31.922 +} 31.923 + 31.924 +/** Get the interned symbol with the given name. 31.925 + * No new symbol is created. 31.926 + * 31.927 + * @return symbol or null 31.928 + */ 31.929 +Sxpr get_symbol(char *sym){ 31.930 + HTEntry *entry; 31.931 + if(!symbols){ 31.932 + if(init_symbols()) return ONOMEM; 31.933 + return ONULL; 31.934 + } 31.935 + entry = HashTable_get_entry(symbols, sym); 31.936 + if(entry){ 31.937 + return OBJP(T_ATOM, entry->value); 31.938 + } else { 31.939 + return ONULL; 31.940 + } 31.941 +} 31.942 + 31.943 +/** Get the interned symbol with the given name. 31.944 + * Creates a new symbol if necessary. 31.945 + * 31.946 + * @return symbol 31.947 + */ 31.948 +Sxpr intern(char *sym){ 31.949 + Sxpr symbol = get_symbol(sym); 31.950 + if(NULLP(symbol)){ 31.951 + if(!symbols) return ONOMEM; 31.952 + symbol = atom_new(sym); 31.953 + if(!NOMEMP(symbol)){ 31.954 + OBJ_ATOM(symbol)->interned = TRUE; 31.955 + HashTable_add(symbols, atom_name(symbol), get_ptr(symbol)); 31.956 + } 31.957 + } 31.958 + return symbol; 31.959 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/tools/libxutil/sxpr.h Wed Nov 24 12:07:16 2004 +0000 32.3 @@ -0,0 +1,420 @@ 32.4 +/* 32.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 32.6 + * 32.7 + * This library is free software; you can redistribute it and/or modify 32.8 + * it under the terms of the GNU Lesser General Public License as 32.9 + * published by the Free Software Foundation; either version 2.1 of the 32.10 + * License, or (at your option) any later version. This library is 32.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 32.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 32.13 + * FITNESS FOR A PARTICULAR PURPOSE. 32.14 + * See the GNU Lesser General Public License for more details. 32.15 + * 32.16 + * You should have received a copy of the GNU Lesser General Public License 32.17 + * along with this library; if not, write to the Free Software Foundation, 32.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 32.19 + */ 32.20 +#ifndef _XUTIL_SXPR_H_ 32.21 +#define _XUTIL_SXPR_H_ 32.22 + 32.23 +#ifdef __KERNEL__ 32.24 +#include <linux/config.h> 32.25 +#include <linux/types.h> 32.26 +#else 32.27 +#include <stdint.h> 32.28 +#endif 32.29 + 32.30 +#include "hash_table.h" 32.31 +#include "iostream.h" 32.32 +#include "allocate.h" 32.33 + 32.34 +/** @file 32.35 + * Definitions for rules and sxprs. 32.36 + */ 32.37 + 32.38 +#ifndef NULL 32.39 +#define NULL 0 32.40 +#endif 32.41 + 32.42 +#ifndef TRUE 32.43 +#define TRUE 1 32.44 +#endif 32.45 + 32.46 +#ifndef FALSE 32.47 +#define FALSE 0 32.48 +#endif 32.49 + 32.50 +/** Sxpr type. */ 32.51 +typedef int16_t TypeCode; 32.52 + 32.53 +/** A typed sxpr handle.*/ 32.54 +typedef struct Sxpr { 32.55 + /** Sxpr type. */ 32.56 + TypeCode type; 32.57 + union { 32.58 + /** Sxpr value. */ 32.59 + unsigned long ul; 32.60 + /** Pointer. */ 32.61 + void *ptr; 32.62 + } v; 32.63 +} Sxpr; 32.64 + 32.65 +/** Sxpr type to indicate out of memory. */ 32.66 +#define T_NOMEM ((TypeCode)-1) 32.67 +/** The 'unspecified' sxpr. */ 32.68 +#define T_NONE ((TypeCode)0) 32.69 +/** The empty list. */ 32.70 +#define T_NULL ((TypeCode)1) 32.71 +/** Unsigned integer. */ 32.72 +#define T_UINT ((TypeCode)2) 32.73 +/** A string. */ 32.74 +#define T_STRING ((TypeCode)3) 32.75 +/** An atom. */ 32.76 +#define T_ATOM ((TypeCode)4) 32.77 +/** A boolean. */ 32.78 +#define T_BOOL ((TypeCode)5) 32.79 + 32.80 +/** A cons (pair or list). */ 32.81 +#define T_CONS ((TypeCode)10) 32.82 + 32.83 +/** An error. */ 32.84 +#define T_ERR ((TypeCode)40) 32.85 + 32.86 +/** An atom. */ 32.87 +typedef struct ObjAtom { 32.88 + Sxpr name; 32.89 + Hashcode hashcode; 32.90 + int interned; 32.91 +} ObjAtom; 32.92 + 32.93 +/** A cons (pair). */ 32.94 +typedef struct ObjCons { 32.95 + Sxpr car; 32.96 + Sxpr cdr; 32.97 +} ObjCons; 32.98 + 32.99 +/** A vector. */ 32.100 +typedef struct ObjVector { 32.101 + int n; 32.102 + Sxpr data[0]; 32.103 +} ObjVector; 32.104 + 32.105 +/** Flags for sxpr printing. */ 32.106 +enum PrintFlags { 32.107 + PRINT_RAW = 0x001, 32.108 + PRINT_TYPE = 0x002, 32.109 + PRINT_PRETTY = 0x004, 32.110 + PRINT_NUM = 0x008, 32.111 +}; 32.112 + 32.113 +/** An integer sxpr. 32.114 + * 32.115 + * @param ty type 32.116 + * @param val integer value 32.117 + */ 32.118 +#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }} 32.119 + 32.120 +/** A pointer sxpr. 32.121 + * If the pointer is non-null, returns an sxpr containing it. 32.122 + * If the pointer is null, returns ONOMEM. 32.123 + * 32.124 + * @param ty type 32.125 + * @param val pointer 32.126 + */ 32.127 +#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM) 32.128 + 32.129 +/** Make an integer sxpr containing a pointer. 32.130 + * 32.131 + * @param val pointer 32.132 + */ 32.133 +#define PTR(val) OBJP(T_UINT, (void*)(val)) 32.134 + 32.135 +/** Make an integer sxpr. 32.136 + * @param x value 32.137 + */ 32.138 +#define OINT(x) OBJI(T_UINT, x) 32.139 + 32.140 +/** Make an error sxpr. 32.141 + * 32.142 + * @param x value 32.143 + */ 32.144 +#define OERR(x) OBJI(T_ERR, x) 32.145 + 32.146 +/** Out of memory constant. */ 32.147 +#define ONOMEM OBJI(T_NOMEM, 0) 32.148 + 32.149 +/** The `unspecified' constant. */ 32.150 +#define ONONE OBJI(T_NONE, 0) 32.151 + 32.152 +/** Empty list constant. */ 32.153 +#define ONULL OBJI(T_NULL, 0) 32.154 + 32.155 +/** False constant. */ 32.156 +#define OFALSE OBJI(T_BOOL, 0) 32.157 + 32.158 +/** True constant. */ 32.159 +#define OTRUE OBJI(T_BOOL, 1) 32.160 + 32.161 +/* Recognizers for the various sxpr types. */ 32.162 +#define ATOMP(obj) has_type(obj, T_ATOM) 32.163 +#define BOOLP(obj) has_type(obj, T_BOOL) 32.164 +#define CONSP(obj) has_type(obj, T_CONS) 32.165 +#define ERRP(obj) has_type(obj, T_ERR) 32.166 +#define INTP(obj) has_type(obj, T_UINT) 32.167 +#define NOMEMP(obj) has_type(obj, T_NOMEM) 32.168 +#define NONEP(obj) has_type(obj, T_NONE) 32.169 +#define NULLP(obj) has_type(obj, T_NULL) 32.170 +#define STRINGP(obj) has_type(obj, T_STRING) 32.171 + 32.172 +#define TRUEP(obj) get_ul(obj) 32.173 + 32.174 +/** Convert an sxpr to an unsigned integer. */ 32.175 +#define OBJ_UINT(x) get_ul(x) 32.176 +/** Convert an sxpr to an integer. */ 32.177 +#define OBJ_INT(x) (int)get_ul(x) 32.178 + 32.179 +/* Conversions of sxprs to their values. 32.180 + * No checking is done. 32.181 + */ 32.182 +#define OBJ_STRING(x) ((char*)get_ptr(x)) 32.183 +#define OBJ_CONS(x) ((ObjCons*)get_ptr(x)) 32.184 +#define OBJ_ATOM(x) ((ObjAtom*)get_ptr(x)) 32.185 +#define OBJ_SET(x) ((ObjSet*)get_ptr(x)) 32.186 +#define CAR(x) (OBJ_CONS(x)->car) 32.187 +#define CDR(x) (OBJ_CONS(x)->cdr) 32.188 + 32.189 +#define CAAR(x) (CAR(CAR(x))) 32.190 +#define CADR(x) (CAR(CDR(x))) 32.191 +#define CDAR(x) (CDR(CAR(x))) 32.192 +#define CDDR(x) (CDR(CDR(x))) 32.193 + 32.194 +/** Get the integer value from an sxpr. 32.195 + * 32.196 + * @param obj sxpr 32.197 + * @return value 32.198 + */ 32.199 +static inline unsigned long get_ul(Sxpr obj){ 32.200 + return obj.v.ul; 32.201 +} 32.202 + 32.203 +/** Get the pointer value from an sxpr. 32.204 + * 32.205 + * @param obj sxpr 32.206 + * @return value 32.207 + */ 32.208 +static inline void * get_ptr(Sxpr obj){ 32.209 + return obj.v.ptr; 32.210 +} 32.211 + 32.212 +/** Create an sxpr containing a pointer. 32.213 + * 32.214 + * @param type typecode 32.215 + * @param val pointer 32.216 + * @return sxpr 32.217 + */ 32.218 +static inline Sxpr obj_ptr(TypeCode type, void *val){ 32.219 + return (Sxpr){ type: type, v: { ptr: val } }; 32.220 +} 32.221 + 32.222 +/** Create an sxpr containing an integer. 32.223 + * 32.224 + * @param type typecode 32.225 + * @param val integer 32.226 + * @return sxpr 32.227 + */ 32.228 +static inline Sxpr obj_ul(TypeCode type, unsigned long val){ 32.229 + return (Sxpr){ type: type, v: { ul: val } }; 32.230 +} 32.231 + 32.232 +/** Get the type of an sxpr. 32.233 + * 32.234 + * @param obj sxpr 32.235 + * @return type 32.236 + */ 32.237 +static inline TypeCode get_type(Sxpr obj){ 32.238 + return obj.type; 32.239 +} 32.240 + 32.241 +/** Check the type of an sxpr. 32.242 + * 32.243 + * @param obj sxpr 32.244 + * @param type to check 32.245 + * @return 1 if has the type, 0 otherwise 32.246 + */ 32.247 +static inline int has_type(Sxpr obj, TypeCode type){ 32.248 + return get_type(obj) == type; 32.249 +} 32.250 + 32.251 +/** Compare sxprs for literal equality of type and value. 32.252 + * 32.253 + * @param x sxpr to compare 32.254 + * @param y sxpr to compare 32.255 + * @return 1 if equal, 0 otherwise 32.256 + */ 32.257 +static inline int eq(Sxpr x, Sxpr y){ 32.258 + return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y))); 32.259 +} 32.260 + 32.261 +/** Checked version of CAR 32.262 + * 32.263 + * @param x sxpr 32.264 + * @return CAR if a cons, x otherwise 32.265 + */ 32.266 +static inline Sxpr car(Sxpr x){ 32.267 + return (CONSP(x) ? CAR(x) : x); 32.268 +} 32.269 + 32.270 +/** Checked version of CDR. 32.271 + * 32.272 + * @param x sxpr 32.273 + * @return CDR if a cons, null otherwise 32.274 + */ 32.275 +static inline Sxpr cdr(Sxpr x){ 32.276 + return (CONSP(x) ? CDR(x) : ONULL); 32.277 +} 32.278 + 32.279 +/** Allocate some memory and return an sxpr containing it. 32.280 + * Returns ONOMEM if allocation failed. 32.281 + * 32.282 + * @param n number of bytes to allocate 32.283 + * @param ty typecode 32.284 + * @return sxpr 32.285 + */ 32.286 +static inline Sxpr halloc(size_t n, TypeCode ty){ 32.287 + return OBJP(ty, allocate(n)); 32.288 +} 32.289 + 32.290 +/** Allocate an sxpr containing a pointer to the given type. 32.291 + * 32.292 + * @param ty type (uses sizeof to determine how many bytes to allocate) 32.293 + * @param code typecode 32.294 + * @return sxpr, ONOMEM if allocation failed 32.295 + */ 32.296 +#define HALLOC(ty, code) halloc(sizeof(ty), code) 32.297 + 32.298 +typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags); 32.299 +typedef int ObjEqualFn(Sxpr obj, Sxpr other); 32.300 +typedef void ObjFreeFn(Sxpr obj); 32.301 + 32.302 +/** An sxpr type definition. */ 32.303 +typedef struct SxprType { 32.304 + TypeCode type; 32.305 + char *name; 32.306 + int pointer; 32.307 + ObjPrintFn *print; 32.308 + ObjEqualFn *equal; 32.309 + ObjFreeFn *free; 32.310 +} SxprType; 32.311 + 32.312 + 32.313 +extern SxprType *get_sxpr_type(int ty); 32.314 + 32.315 +/** Free the pointer in an sxpr. 32.316 + * 32.317 + * @param x sxpr containing a pointer 32.318 + */ 32.319 +static inline void hfree(Sxpr x){ 32.320 + deallocate(get_ptr(x)); 32.321 +} 32.322 + 32.323 +extern int objprint(IOStream *io, Sxpr x, unsigned flags); 32.324 +extern int objequal(Sxpr x, Sxpr y); 32.325 +extern void objfree(Sxpr x); 32.326 + 32.327 +extern void cons_free_cells(Sxpr obj); 32.328 +extern Sxpr intern(char *s); 32.329 + 32.330 +extern Sxpr assoc(Sxpr k, Sxpr l); 32.331 +extern Sxpr assocq(Sxpr k, Sxpr l); 32.332 +extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l); 32.333 +extern Sxpr nrev(Sxpr l); 32.334 +extern Sxpr cons_member(Sxpr l, Sxpr x); 32.335 +extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v); 32.336 +extern int cons_subset(Sxpr s, Sxpr t); 32.337 +extern int cons_set_equal(Sxpr s, Sxpr t); 32.338 + 32.339 +#ifdef USE_GC 32.340 +extern Sxpr cons_remove(Sxpr l, Sxpr x); 32.341 +extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v); 32.342 +#endif 32.343 + 32.344 +extern Sxpr atom_new(char *name); 32.345 +extern char * atom_name(Sxpr obj); 32.346 + 32.347 +extern Sxpr string_new(char *s); 32.348 +extern char * string_string(Sxpr obj); 32.349 +extern int string_length(Sxpr obj); 32.350 + 32.351 +extern Sxpr cons_new(Sxpr car, Sxpr cdr); 32.352 +extern int cons_push(Sxpr *list, Sxpr elt); 32.353 +extern int cons_length(Sxpr obj); 32.354 + 32.355 +Sxpr sxpr_name(Sxpr obj); 32.356 +int sxpr_is(Sxpr obj, char *s); 32.357 +int sxpr_elementp(Sxpr obj, Sxpr name); 32.358 +Sxpr sxpr_attributes(Sxpr obj); 32.359 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def); 32.360 +Sxpr sxpr_children(Sxpr obj); 32.361 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def); 32.362 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def); 32.363 +Sxpr sxpr_child0(Sxpr obj, Sxpr def); 32.364 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def); 32.365 + 32.366 +/** Create a new atom. 32.367 + * 32.368 + * @param s atom name 32.369 + * @return new atom 32.370 + */ 32.371 +static inline Sxpr mkatom(char *s){ 32.372 + return atom_new(s); 32.373 +} 32.374 + 32.375 +/** Create a new string sxpr. 32.376 + * 32.377 + * @param s string bytes (copied) 32.378 + * @return new string 32.379 + */ 32.380 +static inline Sxpr mkstring(char *s){ 32.381 + return string_new(s); 32.382 +} 32.383 + 32.384 +/** Create an integer sxpr. 32.385 + * 32.386 + * @param i value 32.387 + * @return sxpr 32.388 + */ 32.389 +static inline Sxpr mkint(int i){ 32.390 + return OBJI(T_UINT, i); 32.391 +} 32.392 + 32.393 +/** Create a boolean sxpr. 32.394 + * 32.395 + * @param b value 32.396 + * @return sxpr 32.397 + */ 32.398 +static inline Sxpr mkbool(int b){ 32.399 + return OBJI(T_BOOL, (b ? 1 : 0)); 32.400 +} 32.401 + 32.402 +/* Constants used in parsing and printing. */ 32.403 +#define k_list_open "(" 32.404 +#define c_list_open '(' 32.405 +#define k_list_close ")" 32.406 +#define c_list_close ')' 32.407 +#define k_true "true" 32.408 +#define k_false "false" 32.409 + 32.410 +#define c_var '$' 32.411 +#define c_escape '\\' 32.412 +#define c_single_quote '\'' 32.413 +#define c_double_quote '"' 32.414 +#define c_string_open c_double_quote 32.415 +#define c_string_close c_double_quote 32.416 +#define c_data_open '[' 32.417 +#define c_data_close ']' 32.418 +#define c_binary '*' 32.419 +#define c_eval '!' 32.420 +#define c_concat_open '{' 32.421 +#define c_concat_close '}' 32.422 + 32.423 +#endif /* ! _XUTIL_SXPR_H_ */
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/tools/libxutil/sxpr_parser.c Wed Nov 24 12:07:16 2004 +0000 33.3 @@ -0,0 +1,933 @@ 33.4 +/* 33.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 33.6 + * 33.7 + * This library is free software; you can redistribute it and/or modify 33.8 + * it under the terms of the GNU Lesser General Public License as 33.9 + * published by the Free Software Foundation; either version 2.1 of the 33.10 + * License, or (at your option) any later version. This library is 33.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 33.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 33.13 + * FITNESS FOR A PARTICULAR PURPOSE. 33.14 + * See the GNU Lesser General Public License for more details. 33.15 + * 33.16 + * You should have received a copy of the GNU Lesser General Public License 33.17 + * along with this library; if not, write to the Free Software Foundation, 33.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 33.19 + */ 33.20 + 33.21 +#ifdef __KERNEL__ 33.22 +# include <linux/config.h> 33.23 +# include <linux/module.h> 33.24 +# include <linux/kernel.h> 33.25 +# include <linux/string.h> 33.26 +# include <linux/errno.h> 33.27 +#else 33.28 +# include <stdlib.h> 33.29 +# include <errno.h> 33.30 +#endif 33.31 + 33.32 +#include "iostream.h" 33.33 +#include "lexis.h" 33.34 +#include "sxpr_parser.h" 33.35 +#include "sys_string.h" 33.36 +#include "enum.h" 33.37 + 33.38 +/** @file 33.39 + * Sxpr parsing. 33.40 + * 33.41 + * So that the parser does not leak memory, all sxprs constructed by 33.42 + * the parser must be freed on error. On successful parse the sxpr 33.43 + * returned becomes the responsibility of the caller. 33.44 + * 33.45 + * @author Mike Wray <mike.wray@hpl.hp.com> 33.46 + */ 33.47 + 33.48 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args) 33.49 +#define printf(fmt, args...) IOStream_print(iostdout, fmt, ##args) 33.50 + 33.51 +static void reset(Parser *z); 33.52 +static int inputchar(Parser *p, char c); 33.53 +static int savechar(Parser *p, char c); 33.54 +extern void parse_error(Parser *in); 33.55 +extern void parse_error_id(Parser *in, ParseErrorId id); 33.56 + 33.57 +static int begin_start(Parser *p, char c); 33.58 +static int state_start(Parser *p, char c); 33.59 +static int end_start(Parser *p); 33.60 + 33.61 +static int begin_comment(Parser *p, char c); 33.62 +static int state_comment(Parser *p, char c); 33.63 +static int end_comment(Parser *p); 33.64 + 33.65 +static int begin_string(Parser *p, char c); 33.66 +static int state_string(Parser *p, char c); 33.67 +static int end_string(Parser *p); 33.68 +static int state_escape(Parser *p, char c); 33.69 +static int state_octal(Parser *p, char c); 33.70 +static int state_hex(Parser *p, char c); 33.71 + 33.72 +static int begin_atom(Parser *p, char c); 33.73 +static int state_atom(Parser *p, char c); 33.74 +static int end_atom(Parser *p); 33.75 + 33.76 +static int state_list(Parser *p, char c); 33.77 +static int begin_list(Parser *p, char c); 33.78 +static int end_list(Parser *p); 33.79 + 33.80 +/** Print a parse error. 33.81 + * 33.82 + * @param in parser 33.83 + * @param msg format followed by printf arguments 33.84 + */ 33.85 +void eprintf(Parser *in, char *msg, ...){ 33.86 + va_list args; 33.87 + if(in->error_out){ 33.88 + va_start(args, msg); 33.89 + IOStream_vprint(in->error_out, msg, args); 33.90 + va_end(args); 33.91 + } 33.92 +} 33.93 + 33.94 +/** Print a parse warning. 33.95 + * 33.96 + * @param in parser 33.97 + * @param msg format followed by printf arguments 33.98 + */ 33.99 +void wprintf(Parser *in, char *msg, ...){ 33.100 + va_list args; 33.101 + if(in->error_out){ 33.102 + va_start(args, msg); 33.103 + IOStream_vprint(in->error_out, msg, args); 33.104 + va_end(args); 33.105 + } 33.106 +} 33.107 + 33.108 +/*============================================================================*/ 33.109 + 33.110 +/** Record defining the message for a parse error. */ 33.111 +typedef struct { 33.112 + ParseErrorId id; 33.113 + char *message; 33.114 +} ParseError; 33.115 + 33.116 +/** Format for printing parse error messages. */ 33.117 +#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s" 33.118 + 33.119 +/** Message catalog for the parse error codes. */ 33.120 +static ParseError catalog[] = { 33.121 + { PARSE_ERR_UNSPECIFIED, "unspecified error" }, 33.122 + { PARSE_ERR_NOMEM, "out of memory" }, 33.123 + { PARSE_ERR_UNEXPECTED_EOF, "unexpected end of input" }, 33.124 + { PARSE_ERR_TOKEN_TOO_LONG, "token too long" }, 33.125 + { PARSE_ERR_INVALID_SYNTAX, "syntax error" }, 33.126 + { PARSE_ERR_INVALID_ESCAPE, "invalid escape" }, 33.127 + { 0, NULL } 33.128 +}; 33.129 + 33.130 +/** Number of entries in the message catalog. */ 33.131 +const static int catalog_n = sizeof(catalog)/sizeof(ParseError); 33.132 + 33.133 +void ParserState_free(ParserState *z){ 33.134 + if(!z) return; 33.135 + objfree(z->val); 33.136 + deallocate(z); 33.137 +} 33.138 + 33.139 +int ParserState_new(ParserStateFn *fn, char *name, 33.140 + ParserState *parent, ParserState **val){ 33.141 + int err = 0; 33.142 + ParserState *z; 33.143 + z = ALLOCATE(ParserState); 33.144 + if(z){ 33.145 + z->name = name; 33.146 + z->fn = fn; 33.147 + z->parent = parent; 33.148 + z->val = ONULL; 33.149 + } else { 33.150 + err = -ENOMEM; 33.151 + } 33.152 + if(!err) *val = z; 33.153 + return err; 33.154 +} 33.155 + 33.156 +/** Free a parser. 33.157 + * No-op if the parser is null. 33.158 + * 33.159 + * @param z parser 33.160 + */ 33.161 +void Parser_free(Parser *z){ 33.162 + if(!z) return; 33.163 + objfree(z->val); 33.164 + z->val = ONONE; 33.165 + deallocate(z); 33.166 +} 33.167 + 33.168 +/** Create a new parser. The error stream defaults to null. 33.169 + */ 33.170 +Parser * Parser_new(void){ 33.171 + Parser *z = ALLOCATE(Parser); 33.172 + int err = -ENOMEM; 33.173 + 33.174 + if(!z) goto exit; 33.175 + err = 0; 33.176 + reset(z); 33.177 + exit: 33.178 + if(err){ 33.179 + Parser_free(z); 33.180 + z = NULL; 33.181 + } 33.182 + return z; 33.183 +} 33.184 + 33.185 +/** Get the next character. 33.186 + * Records the character read in the parser, 33.187 + * and sets the line and character counts. 33.188 + * 33.189 + * @param p parser 33.190 + * @return error flag: 0 on success, non-zero on error 33.191 + */ 33.192 +static int inputchar(Parser *p, char c){ 33.193 + int err = 0; 33.194 + if(c=='\n'){ 33.195 + p->line_no++; 33.196 + p->char_no = 0; 33.197 + } else { 33.198 + p->char_no++; 33.199 + } 33.200 + return err; 33.201 +} 33.202 + 33.203 +static int savechar(Parser *p, char c){ 33.204 + int err = 0; 33.205 + if(p->buf_i >= p->buf_n){ 33.206 + err = -ENOMEM; 33.207 + goto exit; 33.208 + } 33.209 + p->buf[p->buf_i] = c; 33.210 + p->buf_i++; 33.211 + exit: 33.212 + return err; 33.213 +} 33.214 + 33.215 +int Parser_input_char(Parser *p, char c){ 33.216 + int err = 0; 33.217 + if(at_eof(p)){ 33.218 + //skip; 33.219 + } else { 33.220 + inputchar(p, c); 33.221 + } 33.222 + if(!p->state){ 33.223 + err = begin_start(p, c); 33.224 + if(err) goto exit; 33.225 + } 33.226 + err = p->state->fn(p, c); 33.227 + exit: 33.228 + return err; 33.229 +} 33.230 + 33.231 +int Parser_input_eof(Parser *p){ 33.232 + int err = 0; 33.233 + p->eof = 1; 33.234 + err = Parser_input_char(p, IOSTREAM_EOF); 33.235 + return err; 33.236 +} 33.237 + 33.238 +int Parser_input(Parser *p, char *buf, int buf_n){ 33.239 + int err = 0; 33.240 + int i = 0; 33.241 + if(buf_n <= 0){ 33.242 + err = Parser_input_eof(p); 33.243 + goto exit; 33.244 + } 33.245 + for(i = 0; i<buf_n; i++){ 33.246 + err = Parser_input_char(p, buf[i]); 33.247 + if(err) goto exit; 33.248 + } 33.249 + exit: 33.250 + err = (err < 0 ? err : buf_n); 33.251 + return err; 33.252 +} 33.253 + 33.254 +int Parser_push(Parser *p, ParserStateFn *fn, char *name){ 33.255 + int err = 0; 33.256 + err = ParserState_new(fn, name, p->state, &p->state); 33.257 + return err; 33.258 +} 33.259 + 33.260 +int Parser_pop(Parser *p){ 33.261 + int err = 0; 33.262 + ParserState *s = p->state; 33.263 + p->state = s->parent; 33.264 + if (p->start_state == s) 33.265 + p->start_state = NULL; 33.266 + ParserState_free(s); 33.267 + return err; 33.268 +} 33.269 + 33.270 +int Parser_return(Parser *p){ 33.271 + int err = 0; 33.272 + Sxpr val = ONONE; 33.273 + if(!p->state){ 33.274 + err = -EINVAL; 33.275 + goto exit; 33.276 + } 33.277 + val = p->state->val; 33.278 + p->state->val = ONONE; 33.279 + err = Parser_pop(p); 33.280 + if(err) goto exit; 33.281 + if(p->state){ 33.282 + err = cons_push(&p->state->val, val); 33.283 + } else { 33.284 + val = nrev(val); 33.285 + p->val = val; 33.286 + } 33.287 + exit: 33.288 + if(err){ 33.289 + objfree(val); 33.290 + } 33.291 + return err; 33.292 +} 33.293 + 33.294 +/** Determine if a character is a separator. 33.295 + * 33.296 + * @param p parser 33.297 + * @param c character to test 33.298 + * @return 1 if a separator, 0 otherwise 33.299 + */ 33.300 +static int is_separator(Parser *p, char c){ 33.301 + return in_sep_class(c); 33.302 +} 33.303 + 33.304 +/** Return the current token. 33.305 + * The return value points at the internal buffer, so 33.306 + * it must not be modified (or freed). Use copy_token() if you need a copy. 33.307 + * 33.308 + * @param p parser 33.309 + * @return token 33.310 + */ 33.311 +char *peek_token(Parser *p){ 33.312 + return p->buf; 33.313 +} 33.314 + 33.315 +/** Return a copy of the current token. 33.316 + * The returned value should be freed when finished with. 33.317 + * 33.318 + * @param p parser 33.319 + * @return copy of token 33.320 + */ 33.321 +char *copy_token(Parser *p){ 33.322 + return strdup(peek_token(p)); 33.323 +} 33.324 + 33.325 +static int do_intern(Parser *p){ 33.326 + int err = 0; 33.327 + Sxpr obj = intern(peek_token(p)); 33.328 + if(NOMEMP(obj)){ 33.329 + err = -ENOMEM; 33.330 + } else { 33.331 + p->state->val = obj; 33.332 + } 33.333 + return err; 33.334 +} 33.335 + 33.336 +static int do_string(Parser *p){ 33.337 + int err = 0; 33.338 + Sxpr obj; 33.339 + obj = string_new(peek_token(p)); 33.340 + if(NOMEMP(obj)){ 33.341 + err = -ENOMEM; 33.342 + } else { 33.343 + p->state->val = obj; 33.344 + } 33.345 + return err; 33.346 +} 33.347 + 33.348 +void newtoken(Parser *p){ 33.349 + memset(p->buf, 0, p->buf_n); 33.350 + p->buf_i = 0; 33.351 + p->tok_begin_line = p->line_no; 33.352 + p->tok_begin_char = p->char_no; 33.353 +} 33.354 + 33.355 +int get_escape(char c, char *d){ 33.356 + int err = 0; 33.357 + switch(c){ 33.358 + case 'a': *d = '\a'; break; 33.359 + case 'b': *d = '\b'; break; 33.360 + case 'f': *d = '\f'; break; 33.361 + case 'n': *d = '\n'; break; 33.362 + case 'r': *d = '\r'; break; 33.363 + case 't': *d = '\t'; break; 33.364 + case 'v': *d = '\v'; break; 33.365 + case c_escape: *d = c_escape; break; 33.366 + case c_single_quote: *d = c_single_quote; break; 33.367 + case c_double_quote: *d = c_double_quote; break; 33.368 + default: 33.369 + err = -EINVAL; 33.370 + } 33.371 + return err; 33.372 +} 33.373 + 33.374 +int Parser_ready(Parser *p){ 33.375 + return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val)); 33.376 +} 33.377 + 33.378 +Sxpr Parser_get_val(Parser *p){ 33.379 + Sxpr v = ONONE; 33.380 + if(CONSP(p->val)){ 33.381 + v = CAR(p->val); 33.382 + p->val = CDR(p->val); 33.383 + } else if (CONSP(p->start_state->val)){ 33.384 + p->val = p->start_state->val; 33.385 + p->val = nrev(p->val); 33.386 + p->start_state->val = ONULL; 33.387 + v = CAR(p->val); 33.388 + p->val = CDR(p->val); 33.389 + } 33.390 + return v; 33.391 +} 33.392 + 33.393 +Sxpr Parser_get_all(Parser *p){ 33.394 + Sxpr v = ONULL; 33.395 + if(CONSP(p->val)){ 33.396 + v = p->val; 33.397 + p->val = ONONE; 33.398 + } else if(p->start_state && CONSP(p->start_state->val)){ 33.399 + v = p->start_state->val; 33.400 + p->start_state->val = ONULL; 33.401 + v = nrev(v); 33.402 + } 33.403 + return v; 33.404 +} 33.405 + 33.406 +int begin_start(Parser *p, char c){ 33.407 + int err = 0; 33.408 + err = Parser_push(p, state_start, "start"); 33.409 + if(err) goto exit; 33.410 + p->start_state = p->state; 33.411 + exit: 33.412 + return err; 33.413 +} 33.414 + 33.415 +int state_start(Parser *p, char c){ 33.416 + int err = 0; 33.417 + if(at_eof(p)){ 33.418 + err = end_start(p); 33.419 + } else if(in_space_class(c)){ 33.420 + //skip 33.421 + } else if(in_comment_class(c)){ 33.422 + begin_comment(p, c); 33.423 + } else if(c == c_list_open){ 33.424 + begin_list(p, c); 33.425 + } else if(c == c_list_close){ 33.426 + parse_error(p); 33.427 + err = -EINVAL; 33.428 + } else if(in_string_quote_class(c)){ 33.429 + begin_string(p, c); 33.430 + } else if(in_printable_class(c)){ 33.431 + begin_atom(p, c); 33.432 + } else if(c == 0x04){ 33.433 + //ctrl-D, EOT: end-of-text. 33.434 + Parser_input_eof(p); 33.435 + } else { 33.436 + parse_error(p); 33.437 + err = -EINVAL; 33.438 + } 33.439 + return err; 33.440 +} 33.441 + 33.442 +int end_start(Parser *p){ 33.443 + int err = 0; 33.444 + err = Parser_return(p); 33.445 + return err; 33.446 +} 33.447 + 33.448 +int begin_comment(Parser *p, char c){ 33.449 + int err = 0; 33.450 + err = Parser_push(p, state_comment, "comment"); 33.451 + if(err) goto exit; 33.452 + err = inputchar(p, c); 33.453 + exit: 33.454 + return err; 33.455 +} 33.456 + 33.457 +int state_comment(Parser *p, char c){ 33.458 + int err = 0; 33.459 + if(c == '\n' || at_eof(p)){ 33.460 + err = end_comment(p); 33.461 + } else { 33.462 + err = inputchar(p, c); 33.463 + } 33.464 + return err; 33.465 +} 33.466 + 33.467 +int end_comment(Parser *p){ 33.468 + return Parser_pop(p); 33.469 +} 33.470 + 33.471 +int begin_string(Parser *p, char c){ 33.472 + int err = 0; 33.473 + err = Parser_push(p, state_string, "string"); 33.474 + if(err) goto exit; 33.475 + newtoken(p); 33.476 + p->state->delim = c; 33.477 + exit: 33.478 + return err; 33.479 +} 33.480 + 33.481 +int state_string(Parser *p, char c){ 33.482 + int err = 0; 33.483 + if(at_eof(p)){ 33.484 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.485 + err = -EINVAL; 33.486 + } else if(c == p->state->delim){ 33.487 + err = end_string(p); 33.488 + } else if(c == '\\'){ 33.489 + err = Parser_push(p, state_escape, "escape"); 33.490 + } else { 33.491 + err = savechar(p, c); 33.492 + } 33.493 + return err; 33.494 +} 33.495 + 33.496 +int end_string(Parser *p){ 33.497 + int err = 0; 33.498 + err = do_string(p); 33.499 + if(err) goto exit; 33.500 + err = Parser_return(p); 33.501 + exit: 33.502 + return err; 33.503 +} 33.504 + 33.505 +int state_escape(Parser *p, char c){ 33.506 + int err = 0; 33.507 + char d; 33.508 + if(at_eof(p)){ 33.509 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.510 + err = -EINVAL; 33.511 + goto exit; 33.512 + } 33.513 + if(get_escape(c, &d) == 0){ 33.514 + err = savechar(p, d); 33.515 + if(err) goto exit; 33.516 + err = Parser_pop(p); 33.517 + } else if(c == 'x'){ 33.518 + p->state->fn = state_hex; 33.519 + p->state->ival = 0; 33.520 + p->state->count = 0; 33.521 + } else { 33.522 + p->state->fn = state_octal; 33.523 + p->state->ival = 0; 33.524 + p->state->count = 0; 33.525 + err = Parser_input_char(p, c); 33.526 + } 33.527 + exit: 33.528 + return err; 33.529 +} 33.530 + 33.531 +int octaldone(Parser *p){ 33.532 + int err = 0; 33.533 + char d = (char)(p->state->ival & 0xff); 33.534 + err = Parser_pop(p); 33.535 + if(err) goto exit; 33.536 + err = Parser_input_char(p, d); 33.537 + exit: 33.538 + return err; 33.539 +} 33.540 + 33.541 +int octaldigit(Parser *p, char c){ 33.542 + int err = 0; 33.543 + p->state->ival *= 8; 33.544 + p->state->ival += c - '0'; 33.545 + p->state->count++; 33.546 + if(err) goto exit; 33.547 + if(p->state->ival < 0 || p->state->ival > 0xff){ 33.548 + parse_error(p); 33.549 + err = -EINVAL; 33.550 + goto exit; 33.551 + } 33.552 + if(p->state->count == 3){ 33.553 + err = octaldone(p); 33.554 + } 33.555 + exit: 33.556 + return err; 33.557 +} 33.558 + 33.559 +int state_octal(Parser *p, char c){ 33.560 + int err = 0; 33.561 + if(at_eof(p)){ 33.562 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.563 + err = -EINVAL; 33.564 + goto exit; 33.565 + } else if('0' <= c && c <= '7'){ 33.566 + err = octaldigit(p, c); 33.567 + } else { 33.568 + err = octaldone(p); 33.569 + if(err) goto exit; 33.570 + Parser_input_char(p, c); 33.571 + } 33.572 + exit: 33.573 + return err; 33.574 +} 33.575 + 33.576 +int hexdone(Parser *p){ 33.577 + int err = 0; 33.578 + char d = (char)(p->state->ival & 0xff); 33.579 + err = Parser_pop(p); 33.580 + if(err) goto exit; 33.581 + err = Parser_input_char(p, d); 33.582 + exit: 33.583 + return err; 33.584 +} 33.585 + 33.586 +int hexdigit(Parser *p, char c, char d){ 33.587 + int err = 0; 33.588 + p->state->ival *= 16; 33.589 + p->state->ival += c - d; 33.590 + p->state->count++; 33.591 + if(err) goto exit; 33.592 + if(p->state->ival < 0 || p->state->ival > 0xff){ 33.593 + parse_error(p); 33.594 + err = -EINVAL; 33.595 + goto exit; 33.596 + } 33.597 + if(p->state->count == 2){ 33.598 + err = hexdone(p); 33.599 + } 33.600 + exit: 33.601 + return err; 33.602 +} 33.603 + 33.604 +int state_hex(Parser *p, char c){ 33.605 + int err = 0; 33.606 + if(at_eof(p)){ 33.607 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.608 + err = -EINVAL; 33.609 + goto exit; 33.610 + } else if('0' <= c && c <= '9'){ 33.611 + err = hexdigit(p, c, '0'); 33.612 + } else if('A' <= c && c <= 'F'){ 33.613 + err = hexdigit(p, c, 'A'); 33.614 + } else if('a' <= c && c <= 'f'){ 33.615 + err = hexdigit(p, c, 'a'); 33.616 + } else if(p->state->count){ 33.617 + err =hexdone(p); 33.618 + if(err) goto exit; 33.619 + Parser_input_char(p, c); 33.620 + } 33.621 + exit: 33.622 + return err; 33.623 +} 33.624 + 33.625 +int begin_atom(Parser *p, char c){ 33.626 + int err = 0; 33.627 + err = Parser_push(p, state_atom, "atom"); 33.628 + if(err) goto exit; 33.629 + newtoken(p); 33.630 + err = savechar(p, c); 33.631 + exit: 33.632 + return err; 33.633 +} 33.634 + 33.635 +int state_atom(Parser *p, char c){ 33.636 + int err = 0; 33.637 + if(at_eof(p)){ 33.638 + err = end_atom(p); 33.639 + } else if(is_separator(p, c) || 33.640 + in_space_class(c) || 33.641 + in_comment_class(c)){ 33.642 + err = end_atom(p); 33.643 + if(err) goto exit; 33.644 + err = Parser_input_char(p, c); 33.645 + } else { 33.646 + err = savechar(p, c); 33.647 + } 33.648 + exit: 33.649 + return err; 33.650 +} 33.651 + 33.652 +int end_atom(Parser *p){ 33.653 + int err = 0; 33.654 + err = do_intern(p); 33.655 + if(err) goto exit; 33.656 + err = Parser_return(p); 33.657 + exit: 33.658 + return err; 33.659 +} 33.660 + 33.661 +int state_list(Parser *p, char c){ 33.662 + int err = 0; 33.663 + if(at_eof(p)){ 33.664 + parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF); 33.665 + err = -EINVAL; 33.666 + } else if(c == c_list_close){ 33.667 + p->state->val = nrev(p->state->val); 33.668 + err = end_list(p); 33.669 + } else { 33.670 + err = state_start(p, c); 33.671 + } 33.672 + return err; 33.673 + 33.674 +} 33.675 + 33.676 +int begin_list(Parser *p, char c){ 33.677 + return Parser_push(p, state_list, "list"); 33.678 +} 33.679 + 33.680 +int end_list(Parser *p){ 33.681 + return Parser_return(p); 33.682 +} 33.683 + 33.684 +/** Reset the fields of a parser to initial values. 33.685 + * 33.686 + * @param z parser 33.687 + */ 33.688 +static void reset(Parser *z){ 33.689 + IOStream *error_out = z->error_out; 33.690 + int flags = z->flags; 33.691 + memzero(z, sizeof(Parser)); 33.692 + z->buf_n = sizeof(z->buf) - 1; 33.693 + z->buf_i = 0; 33.694 + z->line_no = 1; 33.695 + z->char_no = 0; 33.696 + z->error_out = error_out; 33.697 + z->flags = flags; 33.698 +} 33.699 + 33.700 +/** Set the parser error stream. 33.701 + * Parse errors are reported on the the error stream if it is non-null. 33.702 + * 33.703 + * @param z parser 33.704 + * @param error_out error stream 33.705 + */ 33.706 +void set_error_stream(Parser *z, IOStream *error_out){ 33.707 + if(z){ 33.708 + z->error_out = error_out; 33.709 + } 33.710 +} 33.711 + 33.712 +/** Get the parser error message for an error code. 33.713 + * 33.714 + * @param id error code 33.715 + * @return error message (empty string if the code is unknown) 33.716 + */ 33.717 +static char *get_message(ParseErrorId id){ 33.718 + int i; 33.719 + for(i=0; i<catalog_n; i++){ 33.720 + if(id == catalog[i].id){ 33.721 + return catalog[i].message; 33.722 + } 33.723 + } 33.724 + return ""; 33.725 +} 33.726 + 33.727 +/** Get the line number. 33.728 + * 33.729 + * @param in parser 33.730 + */ 33.731 +int get_line(Parser *in){ 33.732 + return in->line_no; 33.733 +} 33.734 + 33.735 +/** Get the column number. 33.736 + * 33.737 + * @param in parser 33.738 + */ 33.739 +int get_column(Parser *in){ 33.740 + return in->char_no; 33.741 +} 33.742 + 33.743 +/** Get the line number the current token started on. 33.744 + * 33.745 + * @param in parser 33.746 + */ 33.747 +int get_tok_line(Parser *in){ 33.748 + return in->tok_begin_line; 33.749 +} 33.750 + 33.751 +/** Get the column number the current token started on. 33.752 + * 33.753 + * @param in parser 33.754 + */ 33.755 +int get_tok_column(Parser *in){ 33.756 + return in->tok_begin_char; 33.757 +} 33.758 + 33.759 +/** Report a parse error. 33.760 + * Does nothing if the error stream is null or there is no error. 33.761 + * 33.762 + * @param in parser 33.763 + */ 33.764 +static void report_error(Parser *in){ 33.765 + if(in->error_out && in->err){ 33.766 + char *msg = get_message(in->err); 33.767 + char *tok = peek_token(in); 33.768 + IOStream_print(in->error_out, PARSE_ERR_FMT, 33.769 + get_tok_line(in), get_tok_column(in), msg); 33.770 + if(tok && tok[0]){ 33.771 + IOStream_print(in->error_out, " '%s'", tok); 33.772 + } 33.773 + IOStream_print(in->error_out, "\n"); 33.774 + } 33.775 +} 33.776 + 33.777 +/** Get the error message for the current parse error code. 33.778 + * Does nothing if there is no error. 33.779 + * 33.780 + * @param in parser 33.781 + * @param buf where to place the message 33.782 + * @param n maximum number of characters to place in buf 33.783 + * @return current error code (zero for no error) 33.784 + */ 33.785 +int parse_error_message(Parser *in, char *buf, int n){ 33.786 + if(in->err){ 33.787 + char *msg = get_message(in->err); 33.788 + snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg); 33.789 + } 33.790 + return in->err; 33.791 +} 33.792 + 33.793 +/** Flag an unspecified parse error. All subsequent reads will fail. 33.794 + * 33.795 + * @param in parser 33.796 + */ 33.797 +void parse_error(Parser *in){ 33.798 + parse_error_id(in, PARSE_ERR_INVALID_SYNTAX); 33.799 +} 33.800 + 33.801 +/** Flag a parse error. All subsequent reads will fail. 33.802 + * Does not change the parser error code if it is already set. 33.803 + * 33.804 + * @param in parser 33.805 + * @param id error code 33.806 + */ 33.807 +void parse_error_id(Parser *in, ParseErrorId id){ 33.808 + if(!in->err){ 33.809 + in->err = id; 33.810 + report_error(in); 33.811 + } 33.812 +} 33.813 + 33.814 +/** Test if the parser's error flag is set. 33.815 + * 33.816 + * @param in parser 33.817 + * @return 1 if set, 0 otherwise 33.818 + */ 33.819 +int has_error(Parser *in){ 33.820 + return (in->err > 0); 33.821 +} 33.822 + 33.823 +/** Test if the parser is at end of input. 33.824 + * 33.825 + * @param in parser 33.826 + * @return 1 if at EOF, 0 otherwise 33.827 + */ 33.828 +int at_eof(Parser *p){ 33.829 + return p->eof; 33.830 +} 33.831 + 33.832 +#ifdef SXPR_PARSER_MAIN 33.833 +/* Stuff for standalone testing. */ 33.834 + 33.835 +#include "file_stream.h" 33.836 +#include "string_stream.h" 33.837 + 33.838 +extern int stringof(Sxpr exp, char **s); 33.839 +int child_string(Sxpr exp, Sxpr key, char **s){ 33.840 + int err = 0; 33.841 + Sxpr val = sxpr_child_value(exp, key, ONONE); 33.842 + err = stringof(val, s); 33.843 + return err; 33.844 +} 33.845 + 33.846 +extern int intof(Sxpr exp, int *v); 33.847 +int child_int(Sxpr exp, Sxpr key, int *v){ 33.848 + int err = 0; 33.849 + Sxpr val = sxpr_child_value(exp, key, ONONE); 33.850 + err = intof(val, v); 33.851 + return err; 33.852 +} 33.853 + 33.854 +int eval_vnet(Sxpr exp){ 33.855 + int err = 0; 33.856 + Sxpr oid = intern("id"); 33.857 + int id; 33.858 + err = child_int(exp, oid, &id); 33.859 + if(err) goto exit; 33.860 + dprintf("> vnet id=%d\n", id); 33.861 + exit: 33.862 + dprintf("< err=%d\n", err); 33.863 + return err; 33.864 +} 33.865 + 33.866 +int eval_connect(Sxpr exp){ 33.867 + int err = 0; 33.868 + Sxpr ovif = intern("vif"); 33.869 + Sxpr ovnet = intern("vnet"); 33.870 + char *vif; 33.871 + int vnet; 33.872 + 33.873 + err = child_string(exp, ovif, &vif); 33.874 + if(err) goto exit; 33.875 + err = child_int(exp, ovnet, &vnet); 33.876 + if(err) goto exit; 33.877 + dprintf("> connect vif=%s vnet=%d\n", vif, vnet); 33.878 + exit: 33.879 + dprintf("< err=%d\n", err); 33.880 + return err; 33.881 +} 33.882 + 33.883 +int eval(Sxpr exp){ 33.884 + int err = 0; 33.885 + Sxpr oconnect = intern("connect"); 33.886 + Sxpr ovnet = intern("vnet"); 33.887 + 33.888 + if(sxpr_elementp(exp, ovnet)){ 33.889 + err = eval_vnet(exp); 33.890 + } else if(sxpr_elementp(exp, oconnect)){ 33.891 + err = eval_connect(exp); 33.892 + } else { 33.893 + err = -EINVAL; 33.894 + } 33.895 + return err; 33.896 +} 33.897 + 33.898 +/** Main program for testing. 33.899 + * Parses input and prints it. 33.900 + * 33.901 + * @param argc number of arguments 33.902 + * @param argv arguments 33.903 + * @return error code 33.904 + */ 33.905 +int main(int argc, char *argv[]){ 33.906 + Parser *pin; 33.907 + int err = 0; 33.908 + char buf[1024]; 33.909 + int k; 33.910 + Sxpr obj; 33.911 + //Sxpr l, x; 33.912 + int i = 0; 33.913 + 33.914 + pin = Parser_new(); 33.915 + set_error_stream(pin, iostdout); 33.916 + dprintf("> parse...\n"); 33.917 + while(1){ 33.918 + k = fread(buf, 1, 1, stdin); 33.919 + err = Parser_input(pin, buf, k); 33.920 + while(Parser_ready(pin)){ 33.921 + obj = Parser_get_val(pin); 33.922 + printf("obj %d\n", i++); 33.923 + objprint(iostdout, obj, 0); printf("\n"); 33.924 + } 33.925 + if(k <= 0) break; 33.926 + } 33.927 +/* obj = Parser_get_all(pin); */ 33.928 +/* for(l = obj ; CONSP(l); l = CDR(l)){ */ 33.929 +/* x = CAR(l); */ 33.930 +/* objprint(iostdout, x, 0); printf("\n"); */ 33.931 +/* eval(x); */ 33.932 +/* } */ 33.933 + dprintf("> err=%d\n", err); 33.934 + return 0; 33.935 +} 33.936 +#endif
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/tools/libxutil/sxpr_parser.h Wed Nov 24 12:07:16 2004 +0000 34.3 @@ -0,0 +1,134 @@ 34.4 +/* 34.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 34.6 + * 34.7 + * This library is free software; you can redistribute it and/or modify 34.8 + * it under the terms of the GNU Lesser General Public License as 34.9 + * published by the Free Software Foundation; either version 2.1 of the 34.10 + * License, or (at your option) any later version. This library is 34.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 34.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 34.13 + * FITNESS FOR A PARTICULAR PURPOSE. 34.14 + * See the GNU Lesser General Public License for more details. 34.15 + * 34.16 + * You should have received a copy of the GNU Lesser General Public License 34.17 + * along with this library; if not, write to the Free Software Foundation, 34.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 34.19 + */ 34.20 + 34.21 +#ifndef _XUTIL_SXPR_PARSER_H_ 34.22 +#define _XUTIL_SXPR_PARSER_H_ 34.23 + 34.24 +#include "sxpr.h" 34.25 +#include "iostream.h" 34.26 + 34.27 +/** @file 34.28 + * Sxpr parsing definitions. 34.29 + */ 34.30 + 34.31 +/** Size of a parser input buffer. 34.32 + * Tokens read must fit into this size (including trailing null). 34.33 + */ 34.34 +#define PARSER_BUF_SIZE 1024 34.35 + 34.36 +struct Parser; 34.37 +typedef int ParserStateFn(struct Parser *, char c); 34.38 + 34.39 +typedef struct ParserState { 34.40 + struct ParserState *parent; 34.41 + Sxpr val; 34.42 + int ival; 34.43 + int count; 34.44 + char delim; 34.45 + ParserStateFn *fn; 34.46 + char *name; 34.47 +} ParserState; 34.48 + 34.49 +/** Structure representing an input source for the parser. 34.50 + * Can read from any IOStream implementation. 34.51 + */ 34.52 +typedef struct Parser { 34.53 + Sxpr val; 34.54 + /** Error reporting stream (null for no reports). */ 34.55 + IOStream *error_out; 34.56 + int eof; 34.57 + /** Error flag. Non-zero if there has been a read error. */ 34.58 + int err; 34.59 + /** Line number on input (from 1). */ 34.60 + int line_no; 34.61 + /** Column number of input (reset on new line). */ 34.62 + int char_no; 34.63 + /** Lookahead character. */ 34.64 + char c; 34.65 + /** Buffer for reading tokens. */ 34.66 + char buf[PARSER_BUF_SIZE]; 34.67 + /** Size of token buffer. */ 34.68 + int buf_n; 34.69 + int buf_i; 34.70 + /** Line the last token started on. */ 34.71 + int tok_begin_line; 34.72 + /** Character number the last token started on. */ 34.73 + int tok_begin_char; 34.74 + /** Parsing flags. */ 34.75 + int flags; 34.76 + ParserState *state; 34.77 + ParserState *start_state; 34.78 +} Parser; 34.79 + 34.80 +/** Parser error codes. */ 34.81 +typedef enum { 34.82 + PARSE_ERR_NONE=0, 34.83 + PARSE_ERR_UNSPECIFIED, 34.84 + PARSE_ERR_NOMEM, 34.85 + PARSE_ERR_UNEXPECTED_EOF, 34.86 + PARSE_ERR_TOKEN_TOO_LONG, 34.87 + PARSE_ERR_INVALID_SYNTAX, 34.88 + PARSE_ERR_INVALID_ESCAPE, 34.89 +} ParseErrorId; 34.90 + 34.91 + 34.92 +/** Parser flags. */ 34.93 +//enum { 34.94 +//}; 34.95 + 34.96 +/** Raise some parser flags. 34.97 + * 34.98 + * @param in parser 34.99 + * @param flags flags mask 34.100 + */ 34.101 +inline static void parser_flags_raise(Parser *in, int flags){ 34.102 + in->flags |= flags; 34.103 +} 34.104 + 34.105 +/** Lower some parser flags. 34.106 + * 34.107 + * @param in parser 34.108 + * @param flags flags mask 34.109 + */ 34.110 +inline static void parser_flags_lower(Parser *in, int flags){ 34.111 + in->flags &= ~flags; 34.112 +} 34.113 + 34.114 +/** Clear all parser flags. 34.115 + * 34.116 + * @param in parser 34.117 + */ 34.118 +inline static void parser_flags_clear(Parser *in){ 34.119 + in->flags = 0; 34.120 +} 34.121 + 34.122 +extern void Parser_free(Parser *z); 34.123 +extern Parser * Parser_new(void); 34.124 +extern int Parser_input(Parser *p, char *buf, int buf_n); 34.125 +extern int Parser_input_eof(Parser *p); 34.126 +extern int Parser_input_char(Parser *p, char c); 34.127 +extern void set_error_stream(Parser *z, IOStream *error_out); 34.128 + 34.129 +extern int parse_error_message(Parser *in, char *buf, int n); 34.130 +extern int has_error(Parser *in); 34.131 +extern int at_eof(Parser *in); 34.132 + 34.133 +int Parser_ready(Parser *p); 34.134 +Sxpr Parser_get_val(Parser *p); 34.135 +Sxpr Parser_get_all(Parser *p); 34.136 + 34.137 +#endif /* ! _XUTIL_SXPR_PARSER_H_ */
35.1 --- a/tools/libxutil/sys_net.c Wed Nov 24 11:51:49 2004 +0000 35.2 +++ b/tools/libxutil/sys_net.c Wed Nov 24 12:07:16 2004 +0000 35.3 @@ -232,21 +232,17 @@ char *get_port_service(unsigned long por 35.4 int convert_service_to_port(const char *s, unsigned long *port){ 35.5 int err = 0; 35.6 unsigned long value; 35.7 - printf("%s> %s\n", __FUNCTION__, s); 35.8 if(convert_atoul(s, &value) == 0){ 35.9 int ok = (0 <= value) && (value <= PORT_MAX); 35.10 - printf("> value = %ld\n", value); 35.11 if(ok){ 35.12 value = htons((unsigned short)value); 35.13 } else { 35.14 err = -EINVAL; 35.15 } 35.16 } else { 35.17 - printf("> get_service_port...\n"); 35.18 err = get_service_port(s, &value); 35.19 } 35.20 *port = (err ? 0: value); 35.21 - printf("%s< err=%d\n", __FUNCTION__, err); 35.22 return err; 35.23 } 35.24
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/tools/libxutil/util.c Wed Nov 24 12:07:16 2004 +0000 36.3 @@ -0,0 +1,106 @@ 36.4 +/* 36.5 + * Copyright (C) 2002 - 2004 Mike Wray <mike.wray@hp.com>. 36.6 + * 36.7 + * This library is free software; you can redistribute it and/or modify 36.8 + * it under the terms of the GNU Lesser General Public License as 36.9 + * published by the Free Software Foundation; either version 2.1 of the 36.10 + * License, or (at your option) any later version. This library is 36.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 36.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 36.13 + * FITNESS FOR A PARTICULAR PURPOSE. 36.14 + * See the GNU Lesser General Public License for more details. 36.15 + * 36.16 + * You should have received a copy of the GNU Lesser General Public License 36.17 + * along with this library; if not, write to the Free Software Foundation, 36.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 36.19 + */ 36.20 + 36.21 +#include "sys_net.h" 36.22 +#include "sys_string.h" 36.23 + 36.24 +#ifndef __KERNEL__ 36.25 +# include <grp.h> 36.26 +# include <pwd.h> 36.27 +#endif 36.28 + 36.29 +#include "util.h" 36.30 + 36.31 + 36.32 +/** @file Various utility functions. 36.33 + */ 36.34 + 36.35 +/** Print an address (in network order) as an IPv4 address string 36.36 + * in dot notation. 36.37 + * 36.38 + * @param io where to print address 36.39 + * @param address to print (in network order) 36.40 + * @return bytes printed 36.41 + */ 36.42 +int print_address(IOStream *io, unsigned long address){ 36.43 +#ifdef __KERNEL__ 36.44 + address = ntohl(address); 36.45 + return IOStream_print(io, "%u.%u.%u.%u", 36.46 + (unsigned)((address >> 24) & 0xff), 36.47 + (unsigned)((address >> 16) & 0xff), 36.48 + (unsigned)((address >> 8) & 0xff), 36.49 + (unsigned)((address ) & 0xff)); 36.50 +#else 36.51 + struct in_addr inaddr = { s_addr: address }; 36.52 + return IOStream_print(io, inet_ntoa(inaddr)); 36.53 +#endif 36.54 +} 36.55 + 36.56 +/** Get the protocol number for a protocol. 36.57 + * 36.58 + * @param name protocol name 36.59 + * @param protocol where to put the protocol number 36.60 + * @return 0 if OK, error otherwise 36.61 + */ 36.62 +int get_protocol_number(char *name, unsigned long *protocol){ 36.63 +#ifdef __KERNEL__ 36.64 + return -1; 36.65 +#else 36.66 + struct protoent *proto = getprotobyname(name); 36.67 + if(!proto){ 36.68 + return -1; 36.69 + } 36.70 + *protocol = proto->p_proto; 36.71 + return 0; 36.72 +#endif 36.73 +} 36.74 + 36.75 +/** Get the protocol name for a protocol number. 36.76 + * 36.77 + * @param protocol number 36.78 + * @return name or null 36.79 + */ 36.80 +char *get_protocol_name(unsigned long protocol){ 36.81 +#ifdef __KERNEL__ 36.82 + return 0; 36.83 +#else 36.84 + struct protoent *proto = getprotobynumber(protocol); 36.85 + if(!proto){ 36.86 + return 0; 36.87 + } 36.88 + return proto->p_name; 36.89 +#endif 36.90 +} 36.91 + 36.92 +/** Get the host name for an address. 36.93 + * 36.94 + * @param addr address 36.95 + * @return host name or null 36.96 + */ 36.97 +char *get_host_name(unsigned long addr){ 36.98 +#ifdef __KERNEL__ 36.99 + return 0; 36.100 +#else 36.101 + struct in_addr inaddr; 36.102 + struct hostent *host = 0; 36.103 + 36.104 + inaddr.s_addr = addr; 36.105 + host = gethostbyaddr((char*)&inaddr, sizeof(inaddr), AF_INET); 36.106 + if(!host) return NULL; 36.107 + return host->h_name; 36.108 +#endif 36.109 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/tools/libxutil/util.h Wed Nov 24 12:07:16 2004 +0000 37.3 @@ -0,0 +1,28 @@ 37.4 +/* 37.5 + * Copyright (C) 2002 - 2004 Mike Wray <mike.wray@hp.com>. 37.6 + * 37.7 + * This library is free software; you can redistribute it and/or modify 37.8 + * it under the terms of the GNU Lesser General Public License as 37.9 + * published by the Free Software Foundation; either version 2.1 of the 37.10 + * License, or (at your option) any later version. This library is 37.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 37.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 37.13 + * FITNESS FOR A PARTICULAR PURPOSE. 37.14 + * See the GNU Lesser General Public License for more details. 37.15 + * 37.16 + * You should have received a copy of the GNU Lesser General Public License 37.17 + * along with this library; if not, write to the Free Software Foundation, 37.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 37.19 + */ 37.20 + 37.21 +#ifndef _XEN_LIB_UTIL_H_ 37.22 +#define _XEN_LIB_UTIL_H_ 37.23 + 37.24 +#include "iostream.h" 37.25 + 37.26 +extern int print_address(IOStream *io, unsigned long address); 37.27 +extern int get_protocol_number(char *name, unsigned long *protocol); 37.28 +extern char *get_protocol_name(unsigned long protocol); 37.29 +extern char *get_host_name(unsigned long addr); 37.30 + 37.31 +#endif /* ! _XEN_LIB_UTIL_H_ */
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/tools/vnet/00README Wed Nov 24 12:07:16 2004 +0000 38.3 @@ -0,0 +1,10 @@ 38.4 +This directory contains the implementation of vnets: 38.5 +virtual private networks for virtual machines. 38.6 +See doc/ for more information and examples/ for example 38.7 +configurations. 38.8 + 38.9 +The kernel module is in vnet-module/ and the vnet forwarding 38.10 +daemon is in vnetd/. The vnetd daemon makes vnets work across 38.11 +subnets when multicast routing is not available. 38.12 + 38.13 +Mike Wray <mike.wray@hp.com> 38.14 \ No newline at end of file
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/tools/vnet/Makefile Wed Nov 24 12:07:16 2004 +0000 39.3 @@ -0,0 +1,42 @@ 39.4 + 39.5 +export LINUX_RELEASE ?=2.6 39.6 + 39.7 +all: compile 39.8 + 39.9 +compile: vnetd vnet-module 39.10 + 39.11 +gc.tar.gz: 39.12 + wget http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/$@ 39.13 + 39.14 +gc: gc.tar.gz 39.15 + tar xfz gc.tar.gz 39.16 + ln -sf gc?.? gc 39.17 + 39.18 +gc-install: gc 39.19 + (cd gc && ./configure --prefix=`pwd`/install && make && make install) 39.20 + 39.21 +gc-clean: 39.22 + -$(MAKE) -C gc clean 39.23 + 39.24 +gc-pristine: 39.25 + -rm -rf gc?.? gc 39.26 + 39.27 +.PHONY: vnetd vnet-module install dist clean 39.28 + 39.29 +vnetd: gc-install 39.30 + $(MAKE) -C vnetd 39.31 + 39.32 +vnet-module: 39.33 + $(MAKE) -C vnet-module 39.34 + 39.35 +install: compile 39.36 + $(MAKE) -C vnetd install 39.37 + $(MAKE) -C vnet-module install 39.38 + $(MAKE) -C examples install 39.39 + 39.40 +dist: $(TARGET) 39.41 + $(MAKE) prefix=`pwd`/../../install dist=yes install 39.42 + 39.43 +clean: 39.44 + -$(MAKE) -C vnetd clean 39.45 + -$(MAKE) -C vnet-module clean
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/tools/vnet/doc/vnet-module.txt Wed Nov 24 12:07:16 2004 +0000 40.3 @@ -0,0 +1,50 @@ 40.4 +Vnet Module Command Interface 40.5 +Mike Wray <mike.wray@hp.com> 40.6 +2004/09/17 40.7 + 40.8 +When insmod the vnet-module creates /proc/vnet/policy which 40.9 +can be used to control the module by writing commands into it. 40.10 +The return code from the command should be returned by close. 40.11 + 40.12 +The commands are: 40.13 + 40.14 +(vnet.add (id <id>) [(security { none | auth | conf } )] ) 40.15 + 40.16 +Create the vnet with id <id> and the given security level (default none). 40.17 +Security levels: 40.18 +- none: no security 40.19 +- auth: message authentication (IPSEC hmac) 40.20 +- conf: message confidentiality (IPSEC hmac and encryption) 40.21 + 40.22 +(vnet.del (id <id>)) 40.23 + 40.24 +Delete the vnet with id <id>. 40.25 + 40.26 +(vif.add (vnet <vnetid>) (vmac <macaddr>)) 40.27 + 40.28 +Add the vif with MAC address <macaddr> to the vnet with id <vnetid>. 40.29 +This makes the vnet module respond to VARP requests for <macaddr> 40.30 +on vnet <vnetid>. 40.31 + 40.32 +(vif.del (vnet <vnetid>) (vmac <macaddr>)) 40.33 + 40.34 +Remove the vif with MAC address <macaddr> from the vnet with id <vnetid>. 40.35 +The vnet module will stop responding to VARP for the vif. 40.36 + 40.37 +Examples: 40.38 + 40.39 +To create vnet 10 with no security: 40.40 + 40.41 +echo '(vnet.add (id 10))' > /proc/vnet/policy 40.42 + 40.43 +To create vnet 11 with message authentication: 40.44 + 40.45 +echo '(vnet.add (id 11) (security auth))' > /proc/vnet/policy 40.46 + 40.47 +To add the vif with vmac "aa:00:00:bc:34:ae" to vnet 10: 40.48 + 40.49 +echo '(vif.add (vnet 10) (vmac aa:00:00:bc:34:ae))' > /proc/vnet/policy 40.50 + 40.51 +To remove the vif from the vnet: 40.52 + 40.53 +echo '(vif.del (vnet 10) (vmac aa:00:00:bc:34:ae))' > /proc/vnet/policy
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/tools/vnet/doc/vnet-xend.txt Wed Nov 24 12:07:16 2004 +0000 41.3 @@ -0,0 +1,140 @@ 41.4 + 41.5 +Vnets: Virtual Networks for Virtual Machines 41.6 + 41.7 +Mike Wray <mike.wray@hp.com> 41.8 + 41.9 +0) Introduction 41.10 +--------------- 41.11 + 41.12 +Vnets provide virtual private LANs for virtual machines. 41.13 +This is done using bridging and tunneling. A virtual interface 41.14 +on a vnet can only see other interfaces on the same vnet - it cannot 41.15 +see the real network, and the real network cannot see it either. 41.16 + 41.17 +Virtual interfaces on the same vnet can be on the same machine 41.18 +or on different machines, they can still talk. The hosting machines 41.19 +can even be on different subnets if you run vnetd to forward, 41.20 +or have multicast routing enabled. 41.21 + 41.22 + 41.23 +1) Installing vnet support 41.24 +-------------------------- 41.25 + 41.26 +Assuming the code has been installed (make install in the parent directory), 41.27 +configure xend to use 'network-vnet' instead of the default 'network' to 41.28 +start up networking. This just loads the vnet module when networking starts. 41.29 + 41.30 +In /etc/xend/xend-config.sxp: 41.31 + 41.32 +Configure the network script: 41.33 + 41.34 +(network-script network-vnet) 41.35 + 41.36 +Restart xend. 41.37 + 41.38 +2) Creating vnets 41.39 +----------------- 41.40 + 41.41 +Xend already implements commands to add/remove vnets and 41.42 +bridge to them. To add a vnet use 41.43 + 41.44 +xm call vnet_add <vnet config file> 41.45 + 41.46 +For example, if vnet97.sxp contains: 41.47 + 41.48 +(vnet (id 97) (bridge vnet97) (vnetif vnetif97) (security none)) 41.49 + 41.50 +do 41.51 + 41.52 +xm call vnet_add vnet97.sxp 41.53 + 41.54 +This will define a vnet with id 97 and no security. The bridge for the 41.55 +vnet is called vnet97 and the virtual interface for it is vnetif97. 41.56 +To add an interface on a vm to this vnet simply set its bridge to vnet97 41.57 +in its configuration. 41.58 + 41.59 +In Python: 41.60 + 41.61 +vif="bridge=vnet97" 41.62 + 41.63 +In sxp: 41.64 + 41.65 +(dev (vif (mac aa:00:00:01:02:03) (bridge vnet97))) 41.66 + 41.67 +Once configured, vnets are persistent in the xend database. 41.68 +To remove a vnet use 41.69 + 41.70 +xm call vnet_delete <vnet id> 41.71 + 41.72 +To list vnets use 41.73 + 41.74 +xm call vnets 41.75 + 41.76 +To get information on a vnet id use 41.77 + 41.78 +xm call vnet <vnet id> 41.79 + 41.80 +3) Troubleshooting 41.81 +------------------ 41.82 + 41.83 +The vnet module should appear in 'lsmod'. 41.84 +If a vnet has been configured it should appear in the output of 'xm call vnets'. 41.85 +Its bridge and interface should appear in 'ifconfig'. 41.86 +It should also show in 'brctl show', with its attached interfaces. 41.87 + 41.88 +You can 'see into' a vnet from dom0 if you put an IP address on the bridge. 41.89 +For example, if you have vnet97 with a vm with ip addr 10.0.0.12 on it, 41.90 +then 41.91 + 41.92 +ifconfig vnet97 10.0.0.20 up 41.93 + 41.94 +should let you ping 10.0.0.12 via the vnet97 bridge. 41.95 + 41.96 +4) Examples 41.97 +----------- 41.98 + 41.99 +Here's the full config for a vm on vnet 97, using ip addr 10.0.0.12: 41.100 + 41.101 +(vm 41.102 + (name dom12) 41.103 + (memory '64') 41.104 + (cpu '1') 41.105 + (console '8502') 41.106 + (image 41.107 + (linux 41.108 + (kernel /boot/vmlinuz-2.6.9-xenU) 41.109 + (ip 10.0.0.12:1.2.3.4::::eth0:off) 41.110 + (root /dev/hda1) 41.111 + (args 'rw fastboot 4') 41.112 + ) 41.113 + ) 41.114 + (device (vbd (uname phy:hda2) (dev hda1) (mode w))) 41.115 + (device (vif (mac aa:00:00:11:00:12) (bridge vnet97))) 41.116 +) 41.117 + 41.118 +If you run another vm on the same vnet: 41.119 + 41.120 +(vm 41.121 + (name dom11) 41.122 + (memory '64') 41.123 + (cpu '1') 41.124 + (console '8501') 41.125 + (image 41.126 + (linux 41.127 + (kernel /boot/vmlinuz-2.6.9-xenU) 41.128 + (ip 10.0.0.11:1.2.3.4::::eth0:off) 41.129 + (root /dev/hda1) 41.130 + (args 'rw fastboot 4') 41.131 + ) 41.132 + ) 41.133 + (device (vbd (uname phy:hda3) (dev hda1) (mode w))) 41.134 + (device (vif (mac aa:00:00:11:00:11) (bridge vnet97))) 41.135 +) 41.136 + 41.137 +the vms should be able to talk over the vnet. Check with ping. 41.138 +If they are both on the same machine the connection will simply 41.139 +be the vnet97 bridge, if they are on separate machines their 41.140 +packets will be tunneled in etherip. They should be able to 41.141 +see each other, but not the real network. 41.142 + 41.143 +
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/tools/vnet/examples/Makefile Wed Nov 24 12:07:16 2004 +0000 42.3 @@ -0,0 +1,12 @@ 42.4 +# -*- mode: Makefile; -*- 42.5 +#============================================================================ 42.6 + 42.7 +XEN_SCRIPT_DIR:=/etc/xen/scripts 42.8 + 42.9 +all: 42.10 + 42.11 +install: 42.12 + install -m 0755 -d $(prefix)$(XEN_SCRIPT_DIR) 42.13 + install -m 0554 network-vnet $(prefix)$(XEN_SCRIPT_DIR) 42.14 + 42.15 +clean: 42.16 \ No newline at end of file
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/tools/vnet/examples/network-vnet Wed Nov 24 12:07:16 2004 +0000 43.3 @@ -0,0 +1,218 @@ 43.4 +#!/bin/sh 43.5 +#============================================================================ 43.6 +# Default Xen network start/stop script. 43.7 +# Xend calls a network script when it starts. 43.8 +# The script name to use is defined in /etc/xen/xend-config.sxp 43.9 +# in the network-script field. 43.10 +# 43.11 +# This script creates a bridge (default xen-br0), adds a device 43.12 +# (default eth0) to it, copies the IP addresses from the device 43.13 +# to the bridge and adjusts the routes accordingly. 43.14 +# 43.15 +# If all goes well, this should ensure that networking stays up. 43.16 +# However, some configurations are upset by this, especially 43.17 +# NFS roots. If the bridged setup does not meet your needs, 43.18 +# configure a different script, for example using routing instead. 43.19 +# 43.20 +# Usage: 43.21 +# 43.22 +# network (start|stop|status) {VAR=VAL}* 43.23 +# 43.24 +# Vars: 43.25 +# 43.26 +# bridge The bridge to use (default xen-br0). 43.27 +# netdev The interface to add to the bridge (default eth0). 43.28 +# antispoof Whether to use iptables to prevent spoofing (default yes). 43.29 +# 43.30 +# start: 43.31 +# Creates the bridge and enslaves netdev to it. 43.32 +# Copies the IP addresses from netdev to the bridge. 43.33 +# Deletes the routes to netdev and adds them on bridge. 43.34 +# 43.35 +# stop: 43.36 +# Removes netdev from the bridge. 43.37 +# Deletes the routes to bridge and adds them to netdev. 43.38 +# 43.39 +# status: 43.40 +# Print ifconfig for netdev and bridge. 43.41 +# Print routes. 43.42 +# 43.43 +#============================================================================ 43.44 + 43.45 +# Exit if anything goes wrong. 43.46 +set -e 43.47 + 43.48 +# First arg is the operation. 43.49 +OP=$1 43.50 +shift 43.51 + 43.52 +# Pull variables in args in to environment. 43.53 +for arg ; do export "${arg}" ; done 43.54 + 43.55 +bridge=${bridge:-xen-br0} 43.56 +netdev=${netdev:-eth0} 43.57 +antispoof=${antispoof:-yes} 43.58 + 43.59 +echo "network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof" 43.60 + 43.61 +# Usage: transfer_addrs src dst 43.62 +# Copy all IP addresses (including aliases) from device $src to device $dst. 43.63 +transfer_addrs () { 43.64 + local src=$1 43.65 + local dst=$2 43.66 + # Don't bother if $dst already has IP addresses. 43.67 + if ip addr show dev ${dst} | egrep -q '^ *inet' ; then 43.68 + return 43.69 + fi 43.70 + # Address lines start with 'inet' and have the device in them. 43.71 + # Replace 'inet' with 'ip addr add' and change the device name $src 43.72 + # to 'dev $src'. Remove netmask as we'll add routes later. 43.73 + ip addr show dev ${src} | egrep '^ *inet' | sed -e " 43.74 +s/inet/ip addr add/ 43.75 +s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)/[0-9]\+@\1@ 43.76 +s/${src}/dev ${dst}/ 43.77 +" | sh -e 43.78 +} 43.79 + 43.80 +# Usage: transfer_routes src dst 43.81 +# Get all IP routes to device $src, delete them, and 43.82 +# add the same routes to device $dst. 43.83 +# The original routes have to be deleted, otherwise adding them 43.84 +# for $dst fails (duplicate routes). 43.85 +transfer_routes () { 43.86 + local src=$1 43.87 + local dst=$2 43.88 + # List all routes and grep the ones with $src in. 43.89 + # Stick 'ip route del' on the front to delete. 43.90 + # Change $src to $dst and use 'ip route add' to add. 43.91 + ip route list | grep ${src} | sed -e " 43.92 +h 43.93 +s/^/ip route del / 43.94 +P 43.95 +g 43.96 +s/${src}/${dst}/ 43.97 +s/^/ip route add / 43.98 +P 43.99 +d 43.100 +" | sh -e 43.101 +} 43.102 + 43.103 +# Usage: create_bridge dev bridge 43.104 +# Create bridge $bridge and add device $dev to it. 43.105 +create_bridge () { 43.106 + local dev=$1 43.107 + local bridge=$2 43.108 + 43.109 + # Don't create the bridge if it already exists. 43.110 + if ! brctl show | grep -q ${bridge} ; then 43.111 + brctl addbr ${bridge} 43.112 + brctl stp ${bridge} off 43.113 + brctl setfd ${bridge} 0 43.114 + fi 43.115 + ifconfig ${bridge} up 43.116 +} 43.117 + 43.118 +# Usage: antispoofing dev bridge 43.119 +# Set the default forwarding policy for $dev to drop. 43.120 +# Allow forwarding to the bridge. 43.121 +antispoofing () { 43.122 + local dev=$1 43.123 + local bridge=$2 43.124 + 43.125 + iptables -P FORWARD DROP 43.126 + iptables -A FORWARD -m physdev --physdev-in ${dev} -j ACCEPT 43.127 +} 43.128 + 43.129 +# Usage: show_status dev bridge 43.130 +# Print ifconfig and routes. 43.131 +show_status () { 43.132 + local dev=$1 43.133 + local bridge=$2 43.134 + 43.135 + echo '============================================================' 43.136 + ifconfig ${dev} 43.137 + ifconfig ${bridge} 43.138 + echo ' ' 43.139 + ip route list 43.140 + echo ' ' 43.141 + route -n 43.142 + echo '============================================================' 43.143 +} 43.144 + 43.145 +# Insert the vnet module if it can be found and 43.146 +# it's not already there. 43.147 +vnet_insert () { 43.148 + local module="vnet_module" 43.149 + local mod_dir=/lib/modules/$(uname -r)/kernel 43.150 + local mod_path="${mod_dir}/${module}" 43.151 + local mod_obj="" 43.152 + 43.153 + for ext in ".o" ".ko" ; do 43.154 + f=${mod_path}${ext} 43.155 + if [ -f ${f} ] ; then 43.156 + mod_obj=$f 43.157 + break 43.158 + fi 43.159 + done 43.160 + if [ "${mod_obj}" == "" ] ; then 43.161 + return 43.162 + fi 43.163 + if lsmod | grep -q ${module} ; then 43.164 + echo "VNET: ${module} loaded" 43.165 + else 43.166 + echo "VNET: Loading ${module}..." 43.167 + insmod ${mod_obj} 43.168 + fi 43.169 +} 43.170 + 43.171 +op_start () { 43.172 + if [ "${bridge}" == "null" ] ; then 43.173 + return 43.174 + fi 43.175 + # Create the bridge and give it the interface IP addresses. 43.176 + # Move the interface routes onto the bridge. 43.177 + create_bridge ${netdev} ${bridge} 43.178 + transfer_addrs ${netdev} ${bridge} 43.179 + transfer_routes ${netdev} ${bridge} 43.180 + # Don't add $dev to $bridge if it's already on a bridge. 43.181 + if ! brctl show | grep -q ${netdev} ; then 43.182 + brctl addif ${bridge} ${netdev} 43.183 + fi 43.184 + 43.185 + if [ ${antispoof} == 'yes' ] ; then 43.186 + antispoofing ${netdev} ${bridge} 43.187 + fi 43.188 + 43.189 + vnet_insert 43.190 +} 43.191 + 43.192 +op_stop () { 43.193 + if [ "${bridge}" == "null" ] ; then 43.194 + return 43.195 + fi 43.196 + # Remove the interface from the bridge. 43.197 + # Move the routes back to the interface. 43.198 + brctl delif ${bridge} ${netdev} 43.199 + transfer_routes ${bridge} ${netdev} 43.200 + 43.201 + # It's not our place to be enabling forwarding... 43.202 +} 43.203 + 43.204 +case ${OP} in 43.205 + start) 43.206 + op_start 43.207 + ;; 43.208 + 43.209 + stop) 43.210 + op_stop 43.211 + ;; 43.212 + 43.213 + status) 43.214 + show_status ${netdev} ${bridge} 43.215 + ;; 43.216 + 43.217 + *) 43.218 + echo 'Unknown command: ' ${OP} 43.219 + echo 'Valid commands are: start, stop, status' 43.220 + exit 1 43.221 +esac
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/tools/vnet/examples/vnet97.sxp Wed Nov 24 12:07:16 2004 +0000 44.3 @@ -0,0 +1,3 @@ 44.4 +# Vnet configuration for a vnet with id 97 and no security. 44.5 +# Configure using 'xm call vnet_add vnet97.sxp'. 44.6 +(vnet (id 97) (bridge vnet97) (vnetif vnetif97) (security none))
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/tools/vnet/examples/vnet98.sxp Wed Nov 24 12:07:16 2004 +0000 45.3 @@ -0,0 +1,3 @@ 45.4 +# Vnet configuration for a vnet with id 98 and message authentication. 45.5 +# Configure using 'xm call vnet_add vnet98.sxp'. 45.6 +(vnet (id 98) (bridge vnet98) (vnetif vnetif98) (security auth))
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/tools/vnet/examples/vnet99.sxp Wed Nov 24 12:07:16 2004 +0000 46.3 @@ -0,0 +1,3 @@ 46.4 +# Vnet configuration for a vnet with id 99 and message confidentiality. 46.5 +# Configure using 'xm call vnet_add vnet99.sxp'. 46.6 +(vnet (id 99) (bridge vnet99) (vnetif vnetif99) (security conf))
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/tools/vnet/vnet-module/00README Wed Nov 24 12:07:16 2004 +0000 47.3 @@ -0,0 +1,41 @@ 47.4 +Vnet module for network virtualization. 47.5 +Mike Wray <mike.wray@hp.com> 47.6 + 47.7 +*) Compiling 47.8 +The vnet module can be compiled for 2.4 or 2.6 series kernels. 47.9 +The makefiles use the following variables, which 47.10 +can be set in your env or on the make command line: 47.11 + 47.12 +LINUX_RELEASE: linux release to compile for, 2.4 (default), or 2.6. 47.13 +XENO_ROOT: root of the xen tree containing kernel source. Default '..'. 47.14 +ROOT: root path to install in, default is XENO_ROOT/install. 47.15 + Set to '/' to install relative to filesystem root. 47.16 +KERNEL_VERSION: kernel version, default got from XENO_ROOT. 47.17 +KERNEL_MINOR: kernel minor version, default -xen0. 47.18 +KERNEL_SRC: path to kernel source, default linux-<VERSION> under XENO_ROOT. 47.19 + 47.20 +*) For 2.4 kernel 47.21 + 47.22 +To compile from scratch: 47.23 + 47.24 +make clean 47.25 +make 47.26 + 47.27 +This will build vnet_module.o in the current directory. 47.28 +To install the module use 47.29 + 47.30 +make install 47.31 + 47.32 +*) For 2.6 kernel 47.33 + 47.34 +To compile from scratch: 47.35 + 47.36 +make clean 47.37 +make LINUX_RELEASE=2.6 47.38 + 47.39 +This will build vnet_module.ko in the current directory. 47.40 +To install the module use 47.41 + 47.42 +make LINUX_RELEASE=2.6 install 47.43 + 47.44 +
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/tools/vnet/vnet-module/Makefile Wed Nov 24 12:07:16 2004 +0000 48.3 @@ -0,0 +1,67 @@ 48.4 +# -*- mode: Makefile; -*- 48.5 +#============================================================================ 48.6 +# 48.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 48.8 +# 48.9 +# This program is free software; you can redistribute it and/or modify 48.10 +# it under the terms of the GNU General Public License as published by the 48.11 +# Free Software Foundation; either version 2 of the License, or (at your 48.12 +# option) any later version. 48.13 +# 48.14 +# This program is distributed in the hope that it will be useful, but 48.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 48.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 48.17 +# for more details. 48.18 +# 48.19 +# You should have received a copy of the GNU General Public License along 48.20 +# with this program; if not, write to the Free software Foundation, Inc., 48.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA 48.22 +#============================================================================ 48.23 + 48.24 +#============================================================================ 48.25 +ifeq ($(src),) 48.26 +LINUX_RELEASE ?=2.6 48.27 + 48.28 +include Makefile-$(LINUX_RELEASE) 48.29 + 48.30 +#============================================================================ 48.31 +else 48.32 +#============================================================================ 48.33 +# This section is for the 2.6 kbuild. 48.34 + 48.35 +#$(warning KBUILD_EXTMOD $(KBUILD_EXTMOD)) 48.36 +#$(warning src $(src)) 48.37 +#$(warning obj $(obj)) 48.38 + 48.39 +include $(src)/Makefile.vnet 48.40 + 48.41 +obj-m = vnet_module.o 48.42 +vnet_module-objs = $(VNET_OBJ) 48.43 +vnet_module-objs += $(VNET_LIB_OBJ) 48.44 + 48.45 +#---------------------------------------------------------------------------- 48.46 +# The fancy stuff in the kernel build defeats 'vpath %.c' so we can't 48.47 +# use that to get the lib files compiled. 48.48 +# Setup explicit rules for them using the kbuild C compile rule. 48.49 + 48.50 +# File names in the lib dir. 48.51 +remote_srcs = $(foreach file,$(VNET_LIB_SRC),$(LIB_DIR)/$(file)) 48.52 + 48.53 +# Equivalent file names here. 48.54 +local_srcs = $(foreach file,$(VNET_LIB_SRC),$(src)/$(file)) 48.55 + 48.56 +# Objects for the local names. 48.57 +local_objs = $(local_srcs:.c=.o) 48.58 + 48.59 +# Make the local objects depend on compiling the remote sources. 48.60 +$(local_objs): $(src)/%.o: $(LIB_DIR)/%.c 48.61 + $(call if_changed_rule,cc_o_c) 48.62 +#---------------------------------------------------------------------------- 48.63 + 48.64 +vpath %.h $(LIB_DIR) 48.65 +EXTRA_CFLAGS += -I $(LIB_DIR) 48.66 +EXTRA_CFLAGS += -I $(src) 48.67 + 48.68 +endif 48.69 +#============================================================================ 48.70 +
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 49.2 +++ b/tools/vnet/vnet-module/Makefile-2.4 Wed Nov 24 12:07:16 2004 +0000 49.3 @@ -0,0 +1,97 @@ 49.4 +# -*- mode: Makefile; -*- 49.5 +#============================================================================ 49.6 +# 49.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 49.8 +# 49.9 +# This program is free software; you can redistribute it and/or modify 49.10 +# it under the terms of the GNU General Public License as published by the 49.11 +# Free Software Foundation; either version 2 of the License, or (at your 49.12 +# option) any later version. 49.13 +# 49.14 +# This program is distributed in the hope that it will be useful, but 49.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 49.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 49.17 +# for more details. 49.18 +# 49.19 +# You should have received a copy of the GNU General Public License along 49.20 +# with this program; if not, write to the Free software Foundation, Inc., 49.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA 49.22 +#============================================================================ 49.23 + 49.24 +#============================================================================ 49.25 +# Vnet module makefile for 2.4 series kernels. 49.26 + 49.27 +include Makefile.ver 49.28 + 49.29 +KERNEL_MODULE := vnet_module.o 49.30 + 49.31 +CONFIG_MODVERSIONS := $(shell grep 'CONFIG_MODVERSIONS=y' $(KERNEL_SRC)/.config && echo 1 || echo 0) 49.32 + 49.33 +include Makefile.vnet 49.34 + 49.35 +VNET_OBJ += $(VNET_LIB_OBJ) 49.36 + 49.37 +#---------------------------------------------------------------------------- 49.38 + 49.39 +vpath %.h $(KERNEL_SRC)/include 49.40 +INCLUDES+= -I $(KERNEL_SRC)/include 49.41 + 49.42 +vpath %.h $(LIB_DIR) 49.43 +vpath %.c $(LIB_DIR) 49.44 +INCLUDES += -I $(LIB_DIR) 49.45 + 49.46 +INCLUDES+= -I . 49.47 + 49.48 +#---------------------------------------------------------------------------- 49.49 + 49.50 +CPPFLAGS += -D__KERNEL__ 49.51 +CPPFLAGS += -DMODULE 49.52 + 49.53 +ifeq ($(CONFIG_MODVERSIONS), 1) 49.54 +CPPFLAGS += -DMODVERSIONS 49.55 +CPPFLAGS += -include $(KERNEL_SRC)/include/linux/modversions.h 49.56 +endif 49.57 + 49.58 +CPPFLAGS += $(INCLUDES) 49.59 + 49.60 +CFLAGS += -Wall 49.61 +CFLAGS += -Wstrict-prototypes 49.62 +CFLAGS += -Wno-trigraphs 49.63 +CFLAGS += -Wno-unused-function 49.64 +CFLAGS += -Wno-unused-parameter 49.65 + 49.66 +CFLAGS += -g 49.67 +CFLAGS += -O2 49.68 +CFLAGS += -fno-strict-aliasing 49.69 +CFLAGS += -fno-common 49.70 +#CFLAGS += -fomit-frame-pointer 49.71 + 49.72 +# Dependencies. Gcc generates them for us. 49.73 +CFLAGS += -Wp,-MD,.$(@F).d 49.74 +VNET_DEP = .*.d 49.75 +#---------------------------------------------------------------------------- 49.76 + 49.77 +.PHONY: all 49.78 +all: module 49.79 + 49.80 +.PHONY: module modules 49.81 +module modules: $(KERNEL_MODULE) 49.82 + 49.83 +$(KERNEL_MODULE): $(VNET_OBJ) 49.84 + $(LD) -r -o $@ $^ 49.85 + 49.86 +.PHONY: install install-module modules_install 49.87 +install install-module modules_install: module 49.88 + install -m 0755 -d $(prefix)$(KERNEL_MODULE_DIR) 49.89 + install -m 0554 $(KERNEL_MODULE) $(prefix)$(KERNEL_MODULE_DIR) 49.90 + 49.91 +TAGS: 49.92 + etags *.c *.h 49.93 + 49.94 +.PHONY: clean 49.95 +clean: 49.96 + @rm -f *.a *.o *.ko *~ 49.97 + @rm -f $(VNET_DEP) .*.cmd *.mod.? 49.98 + @rm -rf .tmp_versions 49.99 + 49.100 +-include $(VNET_DEP)
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 50.2 +++ b/tools/vnet/vnet-module/Makefile-2.6 Wed Nov 24 12:07:16 2004 +0000 50.3 @@ -0,0 +1,51 @@ 50.4 +# -*- mode: Makefile; -*- 50.5 +#============================================================================ 50.6 +# 50.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 50.8 +# 50.9 +# This program is free software; you can redistribute it and/or modify 50.10 +# it under the terms of the GNU General Public License as published by the 50.11 +# Free Software Foundation; either version 2 of the License, or (at your 50.12 +# option) any later version. 50.13 +# 50.14 +# This program is distributed in the hope that it will be useful, but 50.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 50.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 50.17 +# for more details. 50.18 +# 50.19 +# You should have received a copy of the GNU General Public License along 50.20 +# with this program; if not, write to the Free software Foundation, Inc., 50.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA 50.22 +#============================================================================ 50.23 + 50.24 +#============================================================================ 50.25 +# Vnet module makefile for 2.6 series kernels. 50.26 + 50.27 +LINUX_RELEASE ?= 2.6 50.28 +include Makefile.ver 50.29 + 50.30 +KERNEL_MODULE = vnet_module.ko 50.31 + 50.32 +#---------------------------------------------------------------------------- 50.33 +#export KBUILD_VERBOSE=1 50.34 + 50.35 +.PHONY: all 50.36 +all: module 50.37 + 50.38 +.PHONY: module 50.39 +module modules: 50.40 + $(MAKE) -C $(KERNEL_SRC) M=`pwd` modules 50.41 + 50.42 +.PHONY: install install-module modules_install 50.43 +install install-module modules_install: module 50.44 + install -m 0755 -d $(prefix)$(KERNEL_MODULE_DIR) 50.45 + install -m 0554 $(KERNEL_MODULE) $(prefix)$(KERNEL_MODULE_DIR) 50.46 + 50.47 +.PHONY: clean 50.48 +clean: 50.49 + @$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean 50.50 + @rm -f *.a *.o *.ko *~ .*.d .*.cmd *.mod.? 50.51 + 50.52 +TAGS: 50.53 + etags *.c *.h 50.54 +
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 51.2 +++ b/tools/vnet/vnet-module/Makefile.ver Wed Nov 24 12:07:16 2004 +0000 51.3 @@ -0,0 +1,49 @@ 51.4 +# -*- mode: Makefile; -*- 51.5 +#============================================================================ 51.6 +# 51.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 51.8 +# 51.9 +# This program is free software; you can redistribute it and/or modify 51.10 +# it under the terms of the GNU General Public License as published by the 51.11 +# Free Software Foundation; either version 2 of the License, or (at your 51.12 +# option) any later version. 51.13 +# 51.14 +# This program is distributed in the hope that it will be useful, but 51.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 51.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 51.17 +# for more details. 51.18 +# 51.19 +# You should have received a copy of the GNU General Public License along 51.20 +# with this program; if not, write to the Free software Foundation, Inc., 51.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA 51.22 +#============================================================================ 51.23 + 51.24 +#---------------------------------------------------------------------------- 51.25 +# Xeno/xen. 51.26 + 51.27 +# Root of xen tree. 51.28 +XEN_ROOT ?=../../.. 51.29 + 51.30 +# Path to relativize the install. Set to / 51.31 +# to install relative to filesystem root. 51.32 +prefix ?=$(XEN_ROOT)/install/ 51.33 +#---------------------------------------------------------------------------- 51.34 + 51.35 +LINUX_RELEASE ?=2.6 51.36 +KERNEL_MINOR ?=-xen0 51.37 + 51.38 +LINUX_VERSION ?= $(shell ( /bin/ls -ld $(XEN_ROOT)/linux-$(LINUX_RELEASE).*-xen-sparse ) 2>/dev/null | \ 51.39 + sed -e 's!^.*linux-\(.\+\)-xen-sparse!\1!' ) 51.40 + 51.41 +ifeq ($(LINUX_VERSION),) 51.42 +$(error Kernel source for linux $(LINUX_RELEASE) not found) 51.43 +endif 51.44 + 51.45 +KERNEL_VERSION =$(LINUX_VERSION)$(KERNEL_MINOR) 51.46 + 51.47 +KERNEL_SRC ?= $(XEN_ROOT)/linux-$(KERNEL_VERSION) 51.48 + 51.49 +KERNEL_MODULE_DIR = /lib/modules/$(KERNEL_VERSION)/kernel 51.50 + 51.51 +#$(warning KERNEL_VERSION $(KERNEL_VERSION)) 51.52 +#$(warning KERNEL_SRC $(KERNEL_SRC))
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/tools/vnet/vnet-module/Makefile.vnet Wed Nov 24 12:07:16 2004 +0000 52.3 @@ -0,0 +1,57 @@ 52.4 +# -*- mode: Makefile; -*- 52.5 +#============================================================================ 52.6 +# 52.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 52.8 +# 52.9 +# This program is free software; you can redistribute it and/or modify 52.10 +# it under the terms of the GNU General Public License as published by the 52.11 +# Free Software Foundation; either version 2 of the License, or (at your 52.12 +# option) any later version. 52.13 +# 52.14 +# This program is distributed in the hope that it will be useful, but 52.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 52.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 52.17 +# for more details. 52.18 +# 52.19 +# You should have received a copy of the GNU General Public License along 52.20 +# with this program; if not, write to the Free software Foundation, Inc., 52.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA 52.22 +#============================================================================ 52.23 + 52.24 +ifeq ($(src),) 52.25 +SRC_DIR= 52.26 +else 52.27 +SRC_DIR=$(src)/ 52.28 +endif 52.29 + 52.30 +LIB_DIR := $(SRC_DIR)../../libxutil 52.31 + 52.32 +VNET_SRC := 52.33 +VNET_SRC += esp.c 52.34 +VNET_SRC += etherip.c 52.35 +VNET_SRC += random.c 52.36 +VNET_SRC += sa_algorithm.c 52.37 +VNET_SRC += sa.c 52.38 +VNET_SRC += skb_context.c 52.39 +VNET_SRC += skb_util.c 52.40 +VNET_SRC += tunnel.c 52.41 +VNET_SRC += varp.c 52.42 +VNET_SRC += varp_socket.c 52.43 +VNET_SRC += vif.c 52.44 +VNET_SRC += vnet.c 52.45 +VNET_SRC += vnet_dev.c 52.46 +VNET_SRC += vnet_ioctl.c 52.47 + 52.48 +VNET_LIB_SRC += allocate.c 52.49 +VNET_LIB_SRC += enum.c 52.50 +VNET_LIB_SRC += hash_table.c 52.51 +VNET_LIB_SRC += iostream.c 52.52 +VNET_LIB_SRC += kernel_stream.c 52.53 +VNET_LIB_SRC += sxpr.c 52.54 +VNET_LIB_SRC += sxpr_parser.c 52.55 +VNET_LIB_SRC += sys_net.c 52.56 +VNET_LIB_SRC += sys_string.c 52.57 + 52.58 +VNET_OBJ := $(VNET_SRC:.c=.o) 52.59 +VNET_LIB_OBJ := $(VNET_LIB_SRC:.c=.o) 52.60 +
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 53.2 +++ b/tools/vnet/vnet-module/esp.c Wed Nov 24 12:07:16 2004 +0000 53.3 @@ -0,0 +1,863 @@ 53.4 +/* 53.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 53.6 + * 53.7 + * This program is free software; you can redistribute it and/or modify 53.8 + * it under the terms of the GNU General Public License as published by the 53.9 + * Free Software Foundation; either version 2 of the License, or (at your 53.10 + * option) any later version. 53.11 + * 53.12 + * This program is distributed in the hope that it will be useful, but 53.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 53.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 53.15 + * for more details. 53.16 + * 53.17 + * You should have received a copy of the GNU General Public License along 53.18 + * with this program; if not, write to the Free software Foundation, Inc., 53.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA 53.20 + * 53.21 + */ 53.22 +#include <linux/config.h> 53.23 +#include <linux/module.h> 53.24 +#include <linux/types.h> 53.25 +#include <linux/sched.h> 53.26 +#include <linux/kernel.h> 53.27 +#include <asm/uaccess.h> 53.28 + 53.29 +#include <linux/init.h> 53.30 + 53.31 +#include <linux/version.h> 53.32 + 53.33 +#include <linux/skbuff.h> 53.34 +#include <linux/netdevice.h> 53.35 +#include <linux/net.h> 53.36 +#include <linux/in.h> 53.37 +#include <linux/inet.h> 53.38 + 53.39 +#include <net/ip.h> 53.40 +#include <net/protocol.h> 53.41 +#include <net/route.h> 53.42 + 53.43 +#include <linux/if_ether.h> 53.44 +#include <linux/icmp.h> 53.45 + 53.46 +#include <asm/scatterlist.h> 53.47 +#include <linux/crypto.h> 53.48 +#include <linux/pfkeyv2.h> 53.49 +#include <linux/random.h> 53.50 + 53.51 +#include <esp.h> 53.52 +#include <sa.h> 53.53 +#include <sa_algorithm.h> 53.54 +#include <tunnel.h> 53.55 +#include <vnet.h> 53.56 +#include <skb_util.h> 53.57 + 53.58 +static const int DEBUG_ICV = 0; 53.59 + 53.60 +#define MODULE_NAME "IPSEC" 53.61 +#define DEBUG 1 53.62 +#undef DEBUG 53.63 +#include "debug.h" 53.64 + 53.65 +/* Outgoing packet: [ eth | ip | data ] 53.66 + * After etherip: [ eth2 | ip2 | ethip | eth | ip | data ] 53.67 + * After esp : [ eth2 | ip2 | esp | {ethip | eth | ip | data} | pad | icv ] 53.68 + * ^ + 53.69 + * The curly braces { ... } denote encryption. 53.70 + * The esp header includes the fixed esp headers and the iv (variable size). 53.71 + * The point marked ^ does not move. To the left is in the header, to the right 53.72 + * is in the frag. Remember that all outgoing skbs (from domains) have 1 frag. 53.73 + * Data after + is added by esp, using an extra frag. 53.74 + * 53.75 + * Incoming as above. 53.76 + * After decrypt: [ eth2 | ip2 | esp | ethip | eth | ip | data | pad | icv ] 53.77 + * Trim tail: [ eth2 | ip2 | esp | ethip | eth | ip | data ] 53.78 + * Drop hdr: [ eth2 | ip2 | ethip | eth | ip | data ] 53.79 + * ^ 53.80 + * The point marked ^ does not move. Incoming skbs are linear (no frags). 53.81 + * The tail is trimmed by adjusting skb->tail and len. 53.82 + * The esp hdr is dropped by using memmove to move the headers and 53.83 + * adjusting the skb pointers. 53.84 + * 53.85 + * todo: Now this code is in linux we can't assume 1 frag for outbound skbs, 53.86 + * or (maybe) that memmove is safe on inbound. 53.87 + */ 53.88 + 53.89 +/** Round n up to a multiple of block. 53.90 + * If block is less than 2 does nothing. 53.91 + * Otherwise assume block is a power of 2. 53.92 + * 53.93 + * @param n to round up 53.94 + * @param block size to round to a multiple of 53.95 + * @return rounded value 53.96 + */ 53.97 +static inline int roundup(int n, int block){ 53.98 + if(block <= 1) return n; 53.99 + block--; 53.100 + return (n + block) & ~block; 53.101 +} 53.102 + 53.103 +/** Check if n is a multiple of block. 53.104 + * If block is less than 2 returns 1. 53.105 + * Otherwise assumes block is a power of 2. 53.106 + * 53.107 + * @param n to check 53.108 + * @param block block size 53.109 + * @return 1 if a multiple, 0 otherwise 53.110 + */ 53.111 +static inline int multipleof(int n, int block){ 53.112 + if(block <= 1) return 1; 53.113 + block--; 53.114 + return !(n & block); 53.115 +} 53.116 + 53.117 +/** Convert from bits to bytes. 53.118 + * 53.119 + * @param n number of bits 53.120 + * @return number of bytes 53.121 + */ 53.122 +static inline int bits_to_bytes(int n){ 53.123 + return n / 8; 53.124 +} 53.125 + 53.126 + 53.127 +/** Insert esp padding at the end of an skb. 53.128 + * Inserts padding bytes, number of padding bytes, protocol number. 53.129 + * 53.130 + * @param skb skb 53.131 + * @param offset offset from skb end to where padding should end 53.132 + * @param extra_n total amount of padding 53.133 + * @param protocol protocol number (from original ip hdr) 53.134 + * @return 0 on success, error code otherwise 53.135 + */ 53.136 +static int esp_sa_pad(struct sk_buff *skb, int offset, int extra_n, 53.137 + unsigned char protocol){ 53.138 + int err; 53.139 + char *data; 53.140 + int pad_n = extra_n - ESP_PAD_N; 53.141 + int i; 53.142 + char buf[extra_n]; 53.143 + 53.144 + data = buf; 53.145 + for(i = 1; i <= pad_n; i++){ 53.146 + *data++ = i; 53.147 + } 53.148 + *data++ = pad_n; 53.149 + *data++ = protocol; 53.150 + err = skb_put_bits(skb, skb->len - offset - extra_n, buf, extra_n); 53.151 + return err; 53.152 +} 53.153 + 53.154 +/** Encrypt skb. Skips esp header and iv. 53.155 + * Assumes skb->data points at esp header. 53.156 + * 53.157 + * @param esp esp state 53.158 + * @parm esph esp header 53.159 + * @param skb packet 53.160 + * @param head_n size of esp header and iv 53.161 + * @param iv_n size of iv 53.162 + * @param text_n size of ciphertext 53.163 + * @return 0 on success, error code otherwise 53.164 + */ 53.165 +static int esp_sa_encrypt(ESPState *esp, ESPHdr *esph, struct sk_buff *skb, 53.166 + int head_n, int iv_n, int text_n){ 53.167 + int err = 0; 53.168 + int sg_n = skb_shinfo(skb)->nr_frags + 1; 53.169 + struct scatterlist sg[sg_n]; 53.170 + 53.171 + err = skb_scatterlist(skb, sg, &sg_n, head_n, text_n); 53.172 + if(err) goto exit; 53.173 + if(iv_n){ 53.174 + crypto_cipher_set_iv(esp->cipher.tfm, esp->cipher.iv, iv_n); 53.175 + } 53.176 + crypto_cipher_encrypt(esp->cipher.tfm, sg, sg, text_n); 53.177 + if(iv_n){ 53.178 + memcpy(esph->data, esp->cipher.iv, iv_n); 53.179 + crypto_cipher_get_iv(esp->cipher.tfm, esp->cipher.iv, iv_n); 53.180 + } 53.181 + exit: 53.182 + return err; 53.183 +} 53.184 + 53.185 +/** Decrypt skb. Skips esp header and iv. 53.186 + * Assumes skb->data points at esp header. 53.187 + * 53.188 + * @param esp esp state 53.189 + * @parm esph esp header 53.190 + * @param skb packet 53.191 + * @param head_n size of esp header and iv 53.192 + * @param iv_n size of iv 53.193 + * @param text_n size of ciphertext 53.194 + * @return 0 on success, error code otherwise 53.195 + */ 53.196 +static int esp_sa_decrypt(ESPState *esp, ESPHdr *esph, struct sk_buff *skb, 53.197 + int head_n, int iv_n, int text_n){ 53.198 + int err = 0; 53.199 + int sg_n = skb_shinfo(skb)->nr_frags + 1; 53.200 + struct scatterlist sg[sg_n]; 53.201 + 53.202 + err = skb_scatterlist(skb, sg, &sg_n, head_n, text_n); 53.203 + if(err) goto exit; 53.204 + if(iv_n){ 53.205 + crypto_cipher_set_iv(esp->cipher.tfm, esph->data, iv_n); 53.206 + } 53.207 + crypto_cipher_decrypt(esp->cipher.tfm, sg, sg, text_n); 53.208 + exit: 53.209 + return err; 53.210 +} 53.211 + 53.212 +/** Compute icv. Includes esp header, iv and ciphertext. 53.213 + * Assumes skb->data points at esp header. 53.214 + * 53.215 + * @param esp esp state 53.216 + * @param skb packet 53.217 + * @param digest_n number of bytes to digest 53.218 + * @param icv_n size of icv 53.219 + * @return 0 on success, error code otherwise 53.220 + */ 53.221 +static int esp_sa_digest(ESPState *esp, struct sk_buff *skb, int digest_n, int icv_n){ 53.222 + int err = 0; 53.223 + u8 icv[icv_n]; 53.224 + 53.225 + if(DEBUG_ICV){ 53.226 + dprintf("> skb digest_n=%d icv_n=%d\n", digest_n, icv_n); 53.227 + skb_print_bits(skb, 0, digest_n); 53.228 + } 53.229 + memset(icv, 0, icv_n); 53.230 + esp->digest.icv(esp, skb, 0, digest_n, icv); 53.231 + skb_put_bits(skb, digest_n, icv, icv_n); 53.232 + return err; 53.233 +} 53.234 + 53.235 +/** Check the icv and trim it from the skb tail. 53.236 + * 53.237 + * @param sa sa state 53.238 + * @param esp esp state 53.239 + * @param esph esp header 53.240 + * @param skb packet 53.241 + * @return 0 on success, error code otherwise 53.242 + */ 53.243 +static int esp_check_icv(SAState *sa, ESPState *esp, ESPHdr *esph, struct sk_buff *skb){ 53.244 + int err = 0; 53.245 + int icv_n = esp->digest.icv_n; 53.246 + int digest_n = skb->len - icv_n; 53.247 + u8 icv_skb[icv_n]; 53.248 + u8 icv_new[icv_n]; 53.249 + 53.250 + dprintf(">\n"); 53.251 + if(DEBUG_ICV){ 53.252 + dprintf("> skb len=%d digest_n=%d icv_n=%d\n", 53.253 + skb->len, digest_n, icv_n); 53.254 + skb_print_bits(skb, 0, skb->len); 53.255 + } 53.256 + if(skb_copy_bits(skb, digest_n, icv_skb, icv_n)){ 53.257 + wprintf("> Error getting icv from skb\n"); 53.258 + goto exit; 53.259 + } 53.260 + esp->digest.icv(esp, skb, 0, digest_n, icv_new); 53.261 + if(DEBUG_ICV){ 53.262 + dprintf("> len=%d icv_n=%d", digest_n, icv_n); 53.263 + printk("\nskb="); buf_print(icv_skb, icv_n); 53.264 + printk("new="); buf_print(icv_new, icv_n); 53.265 + } 53.266 + if(unlikely(memcmp(icv_new, icv_skb, icv_n))){ 53.267 + wprintf("> ICV check failed!\n"); 53.268 + err = -EINVAL; 53.269 + sa->counts.integrity_failures++; 53.270 + goto exit; 53.271 + } 53.272 + skb_trim_tail(skb, icv_n); 53.273 + exit: 53.274 + dprintf("< err=%d\n", err); 53.275 + return err; 53.276 +} 53.277 + 53.278 +/** Send a packet via an ESP SA. 53.279 + * 53.280 + * @param sa SA state 53.281 + * @param skb packet to send 53.282 + * @param tunnel underlying tunnel 53.283 + * @return 0 on success, negative error code otherwise 53.284 + */ 53.285 +static int esp_sa_send(SAState *sa, struct sk_buff *skb, Tunnel *tunnel){ 53.286 + int err = 0; 53.287 + int ip_n; // Size of ip header. 53.288 + int plaintext_n; // Size of plaintext. 53.289 + int ciphertext_n; // Size of ciphertext (including padding). 53.290 + int extra_n; // Extra bytes needed for ciphertext. 53.291 + int icv_n = 0; // Size of integrity check value (icv). 53.292 + int iv_n = 0; // Size of initialization vector (iv). 53.293 + int head_n; // Size of esp header and iv. 53.294 + int tail_n; // Size of esp trailer: padding and icv. 53.295 + ESPState *esp; 53.296 + ESPHdr *esph; 53.297 + 53.298 + dprintf(">\n"); 53.299 + esp = sa->data; 53.300 + ip_n = (skb->nh.iph->ihl << 2); 53.301 + // Assuming skb->data points at ethernet header, exclude ethernet 53.302 + // header and IP header. 53.303 + plaintext_n = skb->len - ETH_HLEN - ip_n; 53.304 + // Add size of padding fields. 53.305 + ciphertext_n = roundup(plaintext_n + ESP_PAD_N, esp->cipher.block_n); 53.306 + if(esp->cipher.pad_n > 0){ 53.307 + ciphertext_n = roundup(ciphertext_n, esp->cipher.pad_n); 53.308 + } 53.309 + extra_n = ciphertext_n - plaintext_n; 53.310 + iv_n = esp->cipher.iv_n; 53.311 + icv_n = esp->digest.icv_n; 53.312 + dprintf("> len=%d plaintext=%d ciphertext=%d extra=%d\n", 53.313 + skb->len, plaintext_n, ciphertext_n, extra_n); 53.314 + dprintf("> iv=%d icv=%d\n", iv_n, icv_n); 53.315 + skb_print_bits(skb, 0, skb->len); 53.316 + 53.317 + // Add headroom for esp header and iv, tailroom for the ciphertext 53.318 + // and icv. 53.319 + head_n = ESP_HDR_N + iv_n; 53.320 + tail_n = extra_n + icv_n; 53.321 + err = skb_make_room(&skb, skb, head_n, tail_n); 53.322 + if(err) goto exit; 53.323 + dprintf("> skb=%p\n", skb); 53.324 + // Move the headers up to make space for the esp header. We can 53.325 + // use memmove() since all this data fits in the skb head. 53.326 + // todo: Can't assume this anymore? 53.327 + dprintf("> header push...\n"); 53.328 + __skb_push(skb, head_n); 53.329 + if(0 && skb->mac.raw){ 53.330 + dprintf("> skb->mac=%p\n", skb->mac.raw); 53.331 + dprintf("> ETH header pull...\n"); 53.332 + memmove(skb->data, skb->mac.raw, ETH_HLEN); 53.333 + skb->mac.raw = skb->data; 53.334 + __skb_pull(skb, ETH_HLEN); 53.335 + } 53.336 + dprintf("> IP header pull...\n"); 53.337 + memmove(skb->data, skb->nh.raw, ip_n); 53.338 + skb->nh.raw = skb->data; 53.339 + __skb_pull(skb, ip_n); 53.340 + esph = (void*)skb->data; 53.341 + // Add spi and sequence number. 53.342 + esph->spi = sa->ident.spi; 53.343 + esph->seq = htonl(++sa->replay.send_seq); 53.344 + // Insert the padding bytes: extra bytes less the pad fields 53.345 + // themselves. 53.346 + dprintf("> esp_sa_pad ...\n"); 53.347 + esp_sa_pad(skb, icv_n, extra_n, skb->nh.iph->protocol); 53.348 + if(sa->security & SA_CONF){ 53.349 + dprintf("> esp_sa_encrypt...\n"); 53.350 + err = esp_sa_encrypt(esp, esph, skb, head_n, iv_n, ciphertext_n); 53.351 + if(err) goto exit; 53.352 + } 53.353 + if(icv_n){ 53.354 + dprintf("> esp_sa_digest...\n"); 53.355 + err = esp_sa_digest(esp, skb, head_n + ciphertext_n, icv_n); 53.356 + if(err) goto exit; 53.357 + } 53.358 + dprintf("> IP header push...\n"); 53.359 + __skb_push(skb, ip_n); 53.360 + if(0 && skb->mac.raw){ 53.361 + dprintf("> ETH header push...\n"); 53.362 + __skb_push(skb, ETH_HLEN); 53.363 + } 53.364 + // Fix ip header. Adjust length field, set protocol, zero 53.365 + // checksum. 53.366 + { 53.367 + // Total packet length (bytes). 53.368 + int tot_len = ntohs(skb->nh.iph->tot_len); 53.369 + tot_len += head_n; 53.370 + tot_len += tail_n; 53.371 + skb->nh.iph->protocol = IPPROTO_ESP; 53.372 + skb->nh.iph->tot_len = htons(tot_len); 53.373 + skb->nh.iph->check = 0; 53.374 + } 53.375 + err = Tunnel_send(tunnel, skb); 53.376 + exit: 53.377 + dprintf("< err=%d\n", err); 53.378 + return err; 53.379 +} 53.380 + 53.381 +/** Release an skb context. 53.382 + * Drops the refcount on the SA. 53.383 + * 53.384 + * @param context to free 53.385 + */ 53.386 +static void esp_context_free_fn(SkbContext *context){ 53.387 + SAState *sa; 53.388 + if(!context) return; 53.389 + sa = context->data; 53.390 + if(!sa) return; 53.391 + context->data = NULL; 53.392 + SAState_decref(sa); 53.393 +} 53.394 + 53.395 +/** Receive a packet via an ESP SA. 53.396 + * Does ESP receive processing (check icv, decrypt), strips 53.397 + * ESP header and re-receives. 53.398 + * 53.399 + * @param sa SA 53.400 + * @param skb packet 53.401 + * @return 0 on success, negative error code otherwise 53.402 + */ 53.403 +static int esp_sa_recv(SAState *sa, struct sk_buff *skb){ 53.404 + int err = -EINVAL; 53.405 + int mine = 0; 53.406 + int vnet = 0; //todo: fixme - need to record skb vnet somewhere 53.407 + ESPState *esp; 53.408 + ESPHdr *esph; 53.409 + ESPPadding *pad; 53.410 + int block_n; // Cipher blocksize. 53.411 + int icv_n; // Size of integrity check value (icv). 53.412 + int iv_n; // Size of initialization vector (iv). 53.413 + int text_n; // Size of text (ciphertext or plaintext). 53.414 + int head_n; // Size of esp header and iv. 53.415 + 53.416 + dprintf("> skb=%p\n", skb); 53.417 + // Assumes skb->data points at esp hdr. 53.418 + esph = (void*)skb->data; 53.419 + esp = sa->data; 53.420 + block_n = crypto_tfm_alg_blocksize(esp->cipher.tfm); 53.421 + icv_n = esp->digest.icv_n; 53.422 + iv_n = esp->cipher.iv_n; 53.423 + head_n = ESP_HDR_N + iv_n; 53.424 + text_n = skb->len - head_n - icv_n; 53.425 + if(text_n < ESP_PAD_N || !multipleof(text_n, block_n)){ 53.426 + wprintf("> Invalid size: text_n=%d tfm:block_n=%d esp:block_n=%d\n", 53.427 + text_n, block_n, esp->cipher.block_n); 53.428 + goto exit; 53.429 + } 53.430 + if(icv_n){ 53.431 + err = esp_check_icv(sa, esp, esph, skb); 53.432 + if(err) goto exit; 53.433 + } 53.434 + mine = 1; 53.435 + if(sa->security & SA_CONF){ 53.436 + err = esp_sa_decrypt(esp, esph, skb, head_n, iv_n, text_n); 53.437 + if(err) goto exit; 53.438 + } 53.439 + // Strip esp header by moving the other headers down. 53.440 + //todo Maybe not safe to do this anymore. 53.441 + memmove(skb->mac.raw + head_n, skb->mac.raw, (skb->data - skb->mac.raw)); 53.442 + skb->mac.raw += head_n; 53.443 + skb->nh.raw += head_n; 53.444 + // Move skb->data back to ethernet header. 53.445 + // Do in 2 moves to ensure offsets are +ve, 53.446 + // since args to skb_pull/skb_push are unsigned. 53.447 + __skb_pull(skb, head_n); 53.448 + __skb_push(skb, skb->data - skb->mac.raw); 53.449 + // After this esph is invalid. 53.450 + esph = NULL; 53.451 + // Trim padding, restore protocol in IP header. 53.452 + pad = skb_trim_tail(skb, ESP_PAD_N); 53.453 + text_n -= ESP_PAD_N; 53.454 + if((pad->pad_n > 255) | (pad->pad_n > text_n)){ 53.455 + wprintf("> Invalid padding: pad_n=%d text_n=%d\n", pad->pad_n, text_n); 53.456 + goto exit; 53.457 + } 53.458 + skb_trim_tail(skb, pad->pad_n); 53.459 + skb->nh.iph->protocol = pad->protocol; 53.460 + err = skb_push_context(skb, vnet, sa->ident.addr, IPPROTO_ESP, 53.461 + sa, esp_context_free_fn); 53.462 + if(err) goto exit; 53.463 + // Increase sa refcount now the skb context refers to it. 53.464 + SAState_incref(sa); 53.465 + err = netif_rx(skb); 53.466 + exit: 53.467 + if(mine) err = 1; 53.468 + dprintf("< skb=%p err=%d\n", skb, err); 53.469 + return err; 53.470 +} 53.471 + 53.472 +/** Estimate the packet size for some data using ESP processing. 53.473 + * 53.474 + * @param sa ESP SA 53.475 + * @param data_n data size 53.476 + * @return size after ESP processing 53.477 + */ 53.478 +static u32 esp_sa_size(SAState *sa, int data_n){ 53.479 + // Even in transport mode have to round up to blocksize. 53.480 + // Have to add some padding for alignment even if pad_n is zero. 53.481 + ESPState *esp = sa->data; 53.482 + 53.483 + data_n = roundup(data_n + ESP_PAD_N, esp->cipher.block_n); 53.484 + if(esp->cipher.pad_n > 0){ 53.485 + data_n = roundup(data_n, esp->cipher.pad_n); 53.486 + } 53.487 + data_n += esp->digest.icv_n; 53.488 + //data_n += esp->cipher.iv_n; 53.489 + data_n += ESP_HDR_N; 53.490 + return data_n; 53.491 +} 53.492 + 53.493 +/** Compute an icv using HMAC digest. 53.494 + * 53.495 + * @param esp ESP state 53.496 + * @param skb packet to digest 53.497 + * @param offset offset to start at 53.498 + * @param len number of bytes to digest 53.499 + * @param icv return parameter for ICV 53.500 + * @return 0 on success, negative error code otherwise 53.501 + */ 53.502 +static inline void esp_hmac_digest(ESPState *esp, struct sk_buff *skb, 53.503 + int offset, int len, u8 *icv){ 53.504 + int err = 0; 53.505 + struct crypto_tfm *digest = esp->digest.tfm; 53.506 + char *icv_tmp = esp->digest.icv_tmp; 53.507 + int sg_n = skb_shinfo(skb)->nr_frags + 1; 53.508 + struct scatterlist sg[sg_n]; 53.509 + 53.510 + dprintf("> offset=%d len=%d\n", offset, len); 53.511 + memset(icv, 0, esp->digest.icv_n); 53.512 + if(DEBUG_ICV){ 53.513 + dprintf("> key len=%d\n", esp->digest.key_n); 53.514 + printk("\nkey="); 53.515 + buf_print(esp->digest.key,esp->digest.key_n); 53.516 + } 53.517 + crypto_hmac_init(digest, esp->digest.key, &esp->digest.key_n); 53.518 + err = skb_scatterlist(skb, sg, &sg_n, offset, len); 53.519 + crypto_hmac_update(digest, sg, sg_n); 53.520 + crypto_hmac_final(digest, esp->digest.key, &esp->digest.key_n, icv_tmp); 53.521 + if(DEBUG_ICV){ 53.522 + dprintf("> digest len=%d ", esp->digest.icv_n); 53.523 + printk("\nval="); 53.524 + buf_print(icv_tmp, esp->digest.icv_n); 53.525 + } 53.526 + memcpy(icv, icv_tmp, esp->digest.icv_n); 53.527 + dprintf("<\n"); 53.528 +} 53.529 + 53.530 +/** Finish up an esp state. 53.531 + * Releases the digest, cipher, iv and frees the state. 53.532 + * 53.533 + * @parma esp state 53.534 + */ 53.535 +static void esp_fini(ESPState *esp){ 53.536 + if(!esp) return; 53.537 + if(esp->digest.tfm){ 53.538 + crypto_free_tfm(esp->digest.tfm); 53.539 + esp->digest.tfm = NULL; 53.540 + } 53.541 + if(esp->digest.icv_tmp){ 53.542 + kfree(esp->digest.icv_tmp); 53.543 + esp->digest.icv_tmp = NULL; 53.544 + } 53.545 + if(esp->cipher.tfm){ 53.546 + crypto_free_tfm(esp->cipher.tfm); 53.547 + esp->cipher.tfm = NULL; 53.548 + } 53.549 + if(esp->cipher.iv){ 53.550 + kfree(esp->cipher.iv); 53.551 + esp->cipher.iv = NULL; 53.552 + } 53.553 + kfree(esp); 53.554 +} 53.555 + 53.556 +/** Release an ESP SA. 53.557 + * 53.558 + * @param sa ESO SA 53.559 + */ 53.560 +static void esp_sa_fini(SAState *sa){ 53.561 + ESPState *esp; 53.562 + if(!sa) return; 53.563 + esp = sa->data; 53.564 + if(!esp) return; 53.565 + esp_fini(esp); 53.566 + sa->data = NULL; 53.567 +} 53.568 + 53.569 +/** Initialize the cipher for an ESP SA. 53.570 + * 53.571 + * @param sa ESP SA 53.572 + * @param esp ESP state 53.573 + * @return 0 on success, negative error code otherwise 53.574 + */ 53.575 +static int esp_cipher_init(SAState *sa, ESPState *esp){ 53.576 + int err = 0; 53.577 + SAAlgorithm *algo = NULL; 53.578 + int cipher_mode = CRYPTO_TFM_MODE_CBC; 53.579 + 53.580 + dprintf("> sa=%p esp=%p\n", sa, esp); 53.581 + dprintf("> cipher=%s\n", sa->cipher.name); 53.582 + algo = sa_cipher_by_name(sa->cipher.name); 53.583 + if(!algo){ 53.584 + wprintf("> Cipher unavailable: %s\n", sa->cipher.name); 53.585 + err = -EINVAL; 53.586 + goto exit; 53.587 + } 53.588 + esp->cipher.key_n = roundup(sa->cipher.bits, 8); 53.589 + // If cipher is null must use ECB because CBC algo does not support blocksize 1. 53.590 + if(strcmp(sa->cipher.name, "cipher_null")){ 53.591 + cipher_mode = CRYPTO_TFM_MODE_ECB; 53.592 + } 53.593 + esp->cipher.tfm = crypto_alloc_tfm(sa->cipher.name, cipher_mode); 53.594 + if(!esp->cipher.tfm){ 53.595 + err = -ENOMEM; 53.596 + goto exit; 53.597 + } 53.598 + esp->cipher.block_n = roundup(crypto_tfm_alg_blocksize(esp->cipher.tfm), 4); 53.599 + esp->cipher.iv_n = crypto_tfm_alg_ivsize(esp->cipher.tfm); 53.600 + esp->cipher.pad_n = 0; 53.601 + if(esp->cipher.iv_n){ 53.602 + esp->cipher.iv = kmalloc(esp->cipher.iv_n, GFP_KERNEL); 53.603 + get_random_bytes(esp->cipher.iv, esp->cipher.iv_n); 53.604 + } 53.605 + crypto_cipher_setkey(esp->cipher.tfm, esp->cipher.key, esp->cipher.key_n); 53.606 + err = 0; 53.607 + exit: 53.608 + dprintf("< err=%d\n", err); 53.609 + return err; 53.610 +} 53.611 + 53.612 +/** Initialize the digest for an ESP SA. 53.613 + * 53.614 + * @param sa ESP SA 53.615 + * @param esp ESP state 53.616 + * @return 0 on success, negative error code otherwise 53.617 + */ 53.618 +static int esp_digest_init(SAState *sa, ESPState *esp){ 53.619 + int err = 0; 53.620 + SAAlgorithm *algo = NULL; 53.621 + 53.622 + dprintf(">\n"); 53.623 + esp->digest.key = sa->digest.key; 53.624 + esp->digest.key_n = bits_to_bytes(roundup(sa->digest.bits, 8)); 53.625 + esp->digest.tfm = crypto_alloc_tfm(sa->digest.name, 0); 53.626 + if(!esp->digest.tfm){ 53.627 + err = -ENOMEM; 53.628 + goto exit; 53.629 + } 53.630 + algo = sa_digest_by_name(sa->digest.name); 53.631 + if(!algo){ 53.632 + wprintf("> Digest unavailable: %s\n", sa->digest.name); 53.633 + err = -EINVAL; 53.634 + goto exit; 53.635 + } 53.636 + esp->digest.icv = esp_hmac_digest; 53.637 + esp->digest.icv_full_n = bits_to_bytes(algo->info.digest.icv_fullbits); 53.638 + esp->digest.icv_n = bits_to_bytes(algo->info.digest.icv_truncbits); 53.639 + 53.640 + if(esp->digest.icv_full_n != crypto_tfm_alg_digestsize(esp->digest.tfm)){ 53.641 + err = -EINVAL; 53.642 + wprintf("> digest %s, size %u != %hu\n", 53.643 + sa->digest.name, 53.644 + crypto_tfm_alg_digestsize(esp->digest.tfm), 53.645 + esp->digest.icv_full_n); 53.646 + goto exit; 53.647 + } 53.648 + 53.649 + esp->digest.icv_tmp = kmalloc(esp->digest.icv_full_n, GFP_KERNEL); 53.650 + if(!esp->digest.icv_tmp){ 53.651 + err = -ENOMEM; 53.652 + goto exit; 53.653 + } 53.654 + exit: 53.655 + dprintf("< err=%d\n", err); 53.656 + return err; 53.657 +} 53.658 + 53.659 +/** Initialize an ESP SA. 53.660 + * 53.661 + * @param sa ESP SA 53.662 + * @param args arguments 53.663 + * @return 0 on success, negative error code otherwise 53.664 + */ 53.665 +static int esp_sa_init(SAState *sa, void *args){ 53.666 + int err = 0; 53.667 + ESPState *esp = NULL; 53.668 + 53.669 + dprintf("> sa=%p\n", sa); 53.670 + esp = kmalloc(sizeof(*esp), GFP_KERNEL); 53.671 + if(!esp){ 53.672 + err = -ENOMEM; 53.673 + goto exit; 53.674 + } 53.675 + *esp = (ESPState){}; 53.676 + err = esp_cipher_init(sa, esp); 53.677 + if(err) goto exit; 53.678 + err = esp_digest_init(sa, esp); 53.679 + if(err) goto exit; 53.680 + sa->data = esp; 53.681 + exit: 53.682 + if(err){ 53.683 + if(esp) esp_fini(esp); 53.684 + } 53.685 + dprintf("< err=%d\n", err); 53.686 + return err; 53.687 +} 53.688 + 53.689 +/** SA type for ESP. 53.690 + */ 53.691 +static SAType esp_sa_type = { 53.692 + .name = "ESP", 53.693 + .protocol = IPPROTO_ESP, 53.694 + .init = esp_sa_init, 53.695 + .fini = esp_sa_fini, 53.696 + .size = esp_sa_size, 53.697 + .recv = esp_sa_recv, 53.698 + .send = esp_sa_send 53.699 +}; 53.700 + 53.701 +/** Get the ESP header from a packet. 53.702 + * 53.703 + * @param skb packet 53.704 + * @param esph return parameter for header 53.705 + * @return 0 on success, negative error code otherwise 53.706 + */ 53.707 +static int esp_skb_header(struct sk_buff *skb, ESPHdr **esph){ 53.708 + int err = 0; 53.709 + if(skb->len < ESP_HDR_N){ 53.710 + err = -EINVAL; 53.711 + goto exit; 53.712 + } 53.713 + *esph = (ESPHdr*)skb->data; 53.714 + exit: 53.715 + return err; 53.716 +} 53.717 + 53.718 +/** Handle an incoming skb with ESP protocol. 53.719 + * 53.720 + * Lookup spi, if state found hand to the state. 53.721 + * If no state, check spi, if ok, create state and pass to it. 53.722 + * If spi not ok, drop. 53.723 + * 53.724 + * @param skb packet 53.725 + * @return 0 on sucess, negative error code otherwise 53.726 + */ 53.727 +static int esp_protocol_recv(struct sk_buff *skb){ 53.728 + int err = 0; 53.729 + const int eth_n = ETH_HLEN; 53.730 + int ip_n; 53.731 + ESPHdr *esph = NULL; 53.732 + SAState *sa = NULL; 53.733 + u32 addr; 53.734 + 53.735 + dprintf(">\n"); 53.736 + dprintf("> recv skb=\n"); skb_print_bits(skb, 0, skb->len); 53.737 + ip_n = (skb->nh.iph->ihl << 2); 53.738 + if(skb->data == skb->mac.raw){ 53.739 + // skb->data points at ethernet header. 53.740 + if (!pskb_may_pull(skb, eth_n + ip_n)){ 53.741 + wprintf("> Malformed skb\n"); 53.742 + err = -EINVAL; 53.743 + goto exit; 53.744 + } 53.745 + skb_pull(skb, eth_n + ip_n); 53.746 + } 53.747 + addr = skb->nh.iph->daddr; 53.748 + err = esp_skb_header(skb, &esph); 53.749 + if(err) goto exit; 53.750 + dprintf("> spi=%08x protocol=%d addr=" IPFMT "\n", 53.751 + esph->spi, IPPROTO_ESP, NIPQUAD(addr)); 53.752 + sa = sa_table_lookup_spi(esph->spi, IPPROTO_ESP, addr); 53.753 + if(!sa){ 53.754 + err = vnet_sa_create(esph->spi, IPPROTO_ESP, addr, &sa); 53.755 + if(err) goto exit; 53.756 + } 53.757 + err = SAState_recv(sa, skb); 53.758 + exit: 53.759 + if(sa) SAState_decref(sa); 53.760 + dprintf("< err=%d\n", err); 53.761 + return err; 53.762 +} 53.763 + 53.764 +/** Handle an ICMP error related to ESP. 53.765 + * 53.766 + * @param skb ICMP error packet 53.767 + * @param info 53.768 + */ 53.769 +static void esp_protocol_icmp_err(struct sk_buff *skb, u32 info){ 53.770 + struct iphdr *iph = (struct iphdr*)skb->data; 53.771 + ESPHdr *esph; 53.772 + SAState *sa; 53.773 + 53.774 + dprintf("> ICMP error type=%d code=%d\n", 53.775 + skb->h.icmph->type, skb->h.icmph->code); 53.776 + if(skb->h.icmph->type != ICMP_DEST_UNREACH || 53.777 + skb->h.icmph->code != ICMP_FRAG_NEEDED){ 53.778 + return; 53.779 + } 53.780 + 53.781 + //todo: need to check skb has enough len to do this. 53.782 + esph = (ESPHdr*)(skb->data + (iph->ihl << 2)); 53.783 + sa = sa_table_lookup_spi(esph->spi, IPPROTO_ESP, iph->daddr); 53.784 + if(!sa) return; 53.785 + wprintf("> ICMP unreachable on SA ESP spi=%08x addr=" IPFMT "\n", 53.786 + ntohl(esph->spi), NIPQUAD(iph->daddr)); 53.787 + SAState_decref(sa); 53.788 +} 53.789 + 53.790 +//============================================================================ 53.791 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 53.792 +// Code for 2.6 kernel. 53.793 + 53.794 +/** Protocol handler for ESP. 53.795 + */ 53.796 +static struct net_protocol esp_protocol = { 53.797 + .handler = esp_protocol_recv, 53.798 + .err_handler = esp_protocol_icmp_err 53.799 +}; 53.800 + 53.801 +static int esp_protocol_add(void){ 53.802 + return inet_add_protocol(&esp_protocol, IPPROTO_ESP); 53.803 +} 53.804 + 53.805 +static int esp_protocol_del(void){ 53.806 + return inet_del_protocol(&esp_protocol, IPPROTO_ESP); 53.807 +} 53.808 + 53.809 +//============================================================================ 53.810 +#else 53.811 +//============================================================================ 53.812 +// Code for 2.4 kernel. 53.813 + 53.814 +/** Protocol handler for ESP. 53.815 + */ 53.816 +static struct inet_protocol esp_protocol = { 53.817 + .name = "ESP", 53.818 + .protocol = IPPROTO_ESP, 53.819 + .handler = esp_protocol_recv, 53.820 + .err_handler = esp_protocol_icmp_err 53.821 +}; 53.822 + 53.823 +static int esp_protocol_add(void){ 53.824 + inet_add_protocol(&esp_protocol); 53.825 + return 0; 53.826 +} 53.827 + 53.828 +static int esp_protocol_del(void){ 53.829 + return inet_del_protocol(&esp_protocol); 53.830 +} 53.831 + 53.832 +#endif 53.833 +//============================================================================ 53.834 + 53.835 + 53.836 +/** Initialize the ESP module. 53.837 + * Registers the ESP protocol and SA type. 53.838 + * 53.839 + * @return 0 on success, negative error code otherwise 53.840 + */ 53.841 +int __init esp_module_init(void){ 53.842 + int err = 0; 53.843 + dprintf(">\n"); 53.844 + err = SAType_add(&esp_sa_type); 53.845 + if(err < 0){ 53.846 + eprintf("> Error adding esp sa type\n"); 53.847 + goto exit; 53.848 + } 53.849 + esp_protocol_add(); 53.850 + exit: 53.851 + dprintf("< err=%d\n", err); 53.852 + return err; 53.853 +} 53.854 + 53.855 +/** Finalize the ESP module. 53.856 + * Deregisters the ESP protocol and SA type. 53.857 + */ 53.858 +void __exit esp_module_exit(void){ 53.859 + if(esp_protocol_del() < 0){ 53.860 + eprintf("> Error removing esp protocol\n"); 53.861 + } 53.862 + if(SAType_del(&esp_sa_type) < 0){ 53.863 + eprintf("> Error removing esp sa type\n"); 53.864 + } 53.865 +} 53.866 +
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 54.2 +++ b/tools/vnet/vnet-module/esp.h Wed Nov 24 12:07:16 2004 +0000 54.3 @@ -0,0 +1,111 @@ 54.4 +/* 54.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 54.6 + * 54.7 + * This program is free software; you can redistribute it and/or modify 54.8 + * it under the terms of the GNU General Public License as published by the 54.9 + * Free Software Foundation; either version 2 of the License, or (at your 54.10 + * option) any later version. 54.11 + * 54.12 + * This program is distributed in the hope that it will be useful, but 54.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 54.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 54.15 + * for more details. 54.16 + * 54.17 + * You should have received a copy of the GNU General Public License along 54.18 + * with this program; if not, write to the Free software Foundation, Inc., 54.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA 54.20 + * 54.21 + */ 54.22 +#ifndef __VNET_ESP_H__ 54.23 +#define __VNET_ESP_H__ 54.24 + 54.25 +#include <linux/config.h> 54.26 +#include <linux/types.h> 54.27 +#include <linux/crypto.h> 54.28 + 54.29 +/** Header used by IPSEC ESP (Encapsulated Security Payload). */ 54.30 +typedef struct ESPHdr { 54.31 + /** The spi (security parameters index). */ 54.32 + u32 spi; 54.33 + /** Sequence number. */ 54.34 + u32 seq; 54.35 + /* Variable length data (depends on crypto suite). 54.36 + Mind the 64 bit alignment! */ 54.37 + u8 data[0]; 54.38 +} ESPHdr; 54.39 + 54.40 +/** Padding trailer used by IPSEC ESP. 54.41 + * Follows the padding itself with the padding length and the 54.42 + * protocol being encapsulated. 54.43 + */ 54.44 +typedef struct ESPPadding { 54.45 + u8 pad_n; 54.46 + u8 protocol; 54.47 +} ESPPadding; 54.48 + 54.49 +/** Size of the esp header (spi and seq). */ 54.50 +static const int ESP_HDR_N = sizeof(ESPHdr); 54.51 + 54.52 +/** Size of the esp pad and next protocol field. */ 54.53 +static const int ESP_PAD_N = sizeof(ESPPadding); 54.54 + 54.55 +enum { 54.56 + SASTATE_VOID, 54.57 + SASTATE_ACQUIRE, 54.58 + SASTATE_VALID, 54.59 + SASTATE_ERROR, 54.60 + SASTATE_EXPIRED, 54.61 + SASTATE_DEAD, 54.62 +}; 54.63 + 54.64 +struct ESPState; 54.65 + 54.66 +/** A cipher instance. */ 54.67 +typedef struct ESPCipher { 54.68 + /** Cipher key. */ 54.69 + u8 *key; 54.70 + /** Key size (bytes). */ 54.71 + int key_n; 54.72 + /** Initialization vector (IV). */ 54.73 + u8 *iv; 54.74 + /** IV size (bytes). */ 54.75 + int iv_n; 54.76 + /** Block size for padding (bytes). */ 54.77 + int pad_n; 54.78 + /** Cipher block size (bytes). */ 54.79 + int block_n; 54.80 + /** Cipher crypto transform. */ 54.81 + struct crypto_tfm *tfm; 54.82 +} ESPCipher; 54.83 + 54.84 +/** A digest instance. */ 54.85 +typedef struct ESPDigest { 54.86 + /** Digest key. */ 54.87 + u8 *key; 54.88 + /** Key size (bytes) */ 54.89 + int key_n; 54.90 + /** ICV size used (bytes). */ 54.91 + u8 icv_n; 54.92 + /** Full ICV size when computed (bytes). */ 54.93 + u8 icv_full_n; 54.94 + /** Working storage for computing ICV. */ 54.95 + u8 *icv_tmp; 54.96 + /** Function used to compute ICV (e.g. HMAC). */ 54.97 + void (*icv)(struct ESPState *esp, 54.98 + struct sk_buff *skb, 54.99 + int offset, 54.100 + int len, 54.101 + u8 *icv); 54.102 + /** Digest crypto transform (e.g. SHA). */ 54.103 + struct crypto_tfm *tfm; 54.104 +} ESPDigest; 54.105 + 54.106 +typedef struct ESPState { 54.107 + struct ESPCipher cipher; 54.108 + struct ESPDigest digest; 54.109 +} ESPState; 54.110 + 54.111 +extern int esp_module_init(void); 54.112 +extern void esp_module_exit(void); 54.113 + 54.114 +#endif /* !__VNET_ESP_H__ */
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 55.2 +++ b/tools/vnet/vnet-module/etherip.c Wed Nov 24 12:07:16 2004 +0000 55.3 @@ -0,0 +1,411 @@ 55.4 +/* 55.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 55.6 + * 55.7 + * This program is free software; you can redistribute it and/or modify 55.8 + * it under the terms of the GNU General Public License as published by the 55.9 + * Free Software Foundation; either version 2 of the License, or (at your 55.10 + * option) any later version. 55.11 + * 55.12 + * This program is distributed in the hope that it will be useful, but 55.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 55.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 55.15 + * for more details. 55.16 + * 55.17 + * You should have received a copy of the GNU General Public License along 55.18 + * with this program; if not, write to the Free software Foundation, Inc., 55.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA 55.20 + * 55.21 + */ 55.22 +#include <linux/config.h> 55.23 +#include <linux/module.h> 55.24 +#include <linux/types.h> 55.25 +#include <linux/kernel.h> 55.26 +#include <linux/init.h> 55.27 + 55.28 +#include <linux/version.h> 55.29 + 55.30 +#include <linux/skbuff.h> 55.31 +#include <linux/net.h> 55.32 +#include <linux/netdevice.h> 55.33 +#include <linux/in.h> 55.34 +#include <linux/inet.h> 55.35 +#include <linux/netfilter_ipv4.h> 55.36 +#include <linux/icmp.h> 55.37 + 55.38 +#include <net/ip.h> 55.39 +#include <net/protocol.h> 55.40 +#include <net/route.h> 55.41 +#include <net/checksum.h> 55.42 + 55.43 +#include <etherip.h> 55.44 +#include <tunnel.h> 55.45 +#include <vnet.h> 55.46 +#include <varp.h> 55.47 +#include <if_varp.h> 55.48 +#include <skb_util.h> 55.49 + 55.50 +#define MODULE_NAME "VNET" 55.51 +//#define DEBUG 1 55.52 +#undef DEBUG 55.53 +#include "debug.h" 55.54 + 55.55 +/** @file Etherip implementation. 55.56 + * The etherip protocol is used to transport Ethernet frames in IP packets. 55.57 + */ 55.58 + 55.59 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 55.60 +#define MAC_ETH(_skb) ((struct ethhdr *)(_skb)->mac.raw) 55.61 +#else 55.62 +#define MAC_ETH(_skb) ((_skb)->mac.ethernet) 55.63 +#endif 55.64 + 55.65 +/** Get the vnet label from an etherip header. 55.66 + * 55.67 + * @param hdr header 55.68 + * @return vnet (in host order) 55.69 + */ 55.70 +int etheriphdr_get_vnet(struct etheriphdr *hdr){ 55.71 +#ifdef CONFIG_ETHERIP_EXT 55.72 + return ntohl(hdr->vnet); 55.73 +#else 55.74 + return hdr->reserved; 55.75 +#endif 55.76 +} 55.77 + 55.78 +/** Set the vnet label in an etherip header. 55.79 + * Also sets the etherip version. 55.80 + * 55.81 + * @param hdr header 55.82 + * @param vnet vnet label (in host order) 55.83 + */ 55.84 +void etheriphdr_set_vnet(struct etheriphdr *hdr, int vnet){ 55.85 +#ifdef CONFIG_ETHERIP_EXT 55.86 + hdr->version = 4; 55.87 + hdr->vnet = htonl(vnet); 55.88 +#else 55.89 + hdr->version = 3; 55.90 + hdr->reserved = vnet & 0x0fff; 55.91 +#endif 55.92 +} 55.93 + 55.94 +/** Open an etherip tunnel. 55.95 + * 55.96 + * @param tunnel to open 55.97 + * @return 0 on success, error code otherwise 55.98 + */ 55.99 +static int etherip_tunnel_open(Tunnel *tunnel){ 55.100 + return 0; 55.101 +} 55.102 + 55.103 +/** Close an etherip tunnel. 55.104 + * 55.105 + * @param tunnel to close 55.106 + */ 55.107 +static void etherip_tunnel_close(Tunnel *tunnel){ 55.108 +} 55.109 + 55.110 + 55.111 +/** Send a packet via an etherip tunnel. 55.112 + * Adds etherip header, new ip header, new ethernet header around 55.113 + * ethernet frame. 55.114 + * 55.115 + * @param tunnel tunnel 55.116 + * @param skb packet 55.117 + * @return 0 on success, error code otherwise 55.118 + */ 55.119 +static int etherip_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){ 55.120 + int err = 0; 55.121 + const int etherip_n = sizeof(struct etheriphdr); 55.122 + const int ip_n = sizeof(struct iphdr); 55.123 + const int eth_n = ETH_HLEN; 55.124 + int head_n = 0; 55.125 + int vnet = tunnel->key.vnet; 55.126 + struct etheriphdr *etheriph; 55.127 + struct ethhdr *ethh; 55.128 + u32 saddr = 0; 55.129 + 55.130 + dprintf("> skb=%p vnet=%d\n", skb, vnet); 55.131 + head_n = etherip_n + ip_n + eth_n; 55.132 + err = skb_make_room(&skb, skb, head_n, 0); 55.133 + if(err) goto exit; 55.134 + 55.135 + //err = vnet_get_device_address(skb->dev, &saddr); 55.136 + //if(err) goto exit; 55.137 + 55.138 + // The original ethernet header. 55.139 + ethh = MAC_ETH(skb); 55.140 + //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len); 55.141 + // Null the pointer as we are pushing a new IP header. 55.142 + skb->mac.raw = NULL; 55.143 + 55.144 + // Setup the etherip header. 55.145 + //dprintf("> push etherip header...\n"); 55.146 + etheriph = (struct etheriphdr *)skb_push(skb, etherip_n); 55.147 + etheriphdr_set_vnet(etheriph, vnet); 55.148 + 55.149 + // Setup the IP header. 55.150 + //dprintf("> push IP header...\n"); 55.151 + skb->nh.raw = skb_push(skb, ip_n); 55.152 + skb->nh.iph->version = 4; // Standard version. 55.153 + skb->nh.iph->ihl = ip_n / 4; // IP header length (32-bit words). 55.154 + skb->nh.iph->tos = 0; // No special type-of-service. 55.155 + skb->nh.iph->tot_len = htons(skb->len); // Total packet length (bytes). 55.156 + skb->nh.iph->id = 0; // No flow id (since no frags). 55.157 + skb->nh.iph->frag_off = htons(IP_DF); // Don't fragment - can't handle frags. 55.158 + skb->nh.iph->ttl = 64; // Linux default time-to-live. 55.159 + skb->nh.iph->protocol = IPPROTO_ETHERIP; // IP protocol number. 55.160 + skb->nh.iph->saddr = saddr; // Source address. 55.161 + skb->nh.iph->daddr = tunnel->key.addr; // Destination address. 55.162 + skb->nh.iph->check = 0; 55.163 + 55.164 + // Ethernet header will be filled-in by device. 55.165 + err = Tunnel_send(tunnel->base, skb); 55.166 + skb = NULL; 55.167 + exit: 55.168 + if(err && skb) dev_kfree_skb(skb); 55.169 + //dprintf("< err=%d\n", err); 55.170 + return err; 55.171 +} 55.172 + 55.173 +/** Tunnel type for etherip. 55.174 + */ 55.175 +static TunnelType _etherip_tunnel_type = { 55.176 + .name = "ETHERIP", 55.177 + .open = etherip_tunnel_open, 55.178 + .close = etherip_tunnel_close, 55.179 + .send = etherip_tunnel_send 55.180 +}; 55.181 + 55.182 +TunnelType *etherip_tunnel_type = &_etherip_tunnel_type; 55.183 + 55.184 +/* Defeat compiler warnings about unused functions. */ 55.185 +static void print_str(char *s, int n) __attribute__((unused)); 55.186 + 55.187 +static void print_str(char *s, int n) { 55.188 + int i; 55.189 + 55.190 + for(i=0; i<n; s++, i++){ 55.191 + if(i && i % 40 == 0) printk("\n"); 55.192 + if(('a'<= *s && *s <= 'z') || 55.193 + ('A'<= *s && *s <= 'Z') || 55.194 + ('0'<= *s && *s <= '9')){ 55.195 + printk("%c", *s); 55.196 + } else { 55.197 + printk("<%x>", (unsigned)(0xff & *s)); 55.198 + } 55.199 + } 55.200 + printk("\n"); 55.201 +} 55.202 + 55.203 +/** Do etherip receive processing. 55.204 + * Strips etherip header to extract the ethernet frame, sets 55.205 + * the vnet from the header and re-receives the frame. 55.206 + * 55.207 + * @param skb packet 55.208 + * @return 0 on success, error code otherwise 55.209 + */ 55.210 +static int etherip_protocol_recv(struct sk_buff *skb){ 55.211 + int err = 0; 55.212 + int mine = 0; 55.213 + const int eth_n = ETH_HLEN; 55.214 + int ip_n; 55.215 + const int etherip_n = sizeof(struct etheriphdr); 55.216 + struct etheriphdr *etheriph; 55.217 + struct ethhdr *ethhdr; 55.218 + Vnet *vinfo = NULL; 55.219 + u32 vnet; 55.220 + 55.221 + ethhdr = MAC_ETH(skb); 55.222 + if(MULTICAST(skb->nh.iph->daddr) && 55.223 + (skb->nh.iph->daddr != varp_mcast_addr)){ 55.224 + // Ignore multicast packets not addressed to us. 55.225 + dprintf("> dst=%u.%u.%u.%u varp_mcast_addr=%u.%u.%u.%u\n", 55.226 + NIPQUAD(skb->nh.iph->daddr), 55.227 + NIPQUAD(varp_mcast_addr)); 55.228 + goto exit; 55.229 + } 55.230 + ip_n = (skb->nh.iph->ihl << 2); 55.231 + if(skb->data == skb->mac.raw){ 55.232 + // skb->data points at ethernet header. 55.233 + //dprintf("> len=%d\n", skb->len); 55.234 + if (!pskb_may_pull(skb, eth_n + ip_n)){ 55.235 + wprintf("> Malformed skb\n"); 55.236 + err = -EINVAL; 55.237 + goto exit; 55.238 + } 55.239 + skb_pull(skb, eth_n + ip_n); 55.240 + } 55.241 + // Assume skb->data points at etherip header. 55.242 + etheriph = (void*)skb->data; 55.243 + if(!pskb_may_pull(skb, etherip_n)){ 55.244 + wprintf("> Malformed skb\n"); 55.245 + err = -EINVAL; 55.246 + goto exit; 55.247 + } 55.248 + vnet = etheriphdr_get_vnet(etheriph); 55.249 + dprintf("> Rcvd skb=%p vnet=%d\n", skb, vnet); 55.250 + // If vnet is secure, context must include IPSEC ESP. 55.251 + err = vnet_check_context(vnet, SKB_CONTEXT(skb), &vinfo); 55.252 + Vnet_decref(vinfo); 55.253 + if(err){ 55.254 + wprintf("> Failed security check\n"); 55.255 + goto exit; 55.256 + } 55.257 + mine = 1; 55.258 + // Point at the headers in the contained ethernet frame. 55.259 + skb->mac.raw = skb_pull(skb, etherip_n); 55.260 + 55.261 + // Know source ip, vnet, vmac, so could update varp cache. 55.262 + // But if traffic comes to us over a vnetd tunnel this points the coa 55.263 + // at the vnetd rather than the endpoint. So don't do it. 55.264 + //varp_update(htonl(vnet), MAC_ETH(skb)->h_source, skb->nh.iph->saddr); 55.265 + 55.266 + // Assuming a standard Ethernet frame. 55.267 + skb->nh.raw = skb_pull(skb, ETH_HLEN); 55.268 + 55.269 +#ifdef CONFIG_NETFILTER 55.270 +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) 55.271 + // This stops our new pkt header being clobbered by a subsequent 55.272 + // call to nf_bridge_maybe_copy_header. Just replicate the 55.273 + // corresponding nf_bridge_save_header. 55.274 + if(skb->nf_bridge){ 55.275 + int header_size = 16; 55.276 + if(MAC_ETH(skb)->h_proto == __constant_htons(ETH_P_8021Q)) { 55.277 + header_size = 18; 55.278 + } 55.279 + memcpy(skb->nf_bridge->data, skb->data - header_size, header_size); 55.280 + } 55.281 +#endif 55.282 +#endif 55.283 + 55.284 + if(1){ 55.285 + struct ethhdr *eth = MAC_ETH(skb); 55.286 + // Devices use eth_type_trans() to set skb->pkt_type and skb->protocol. 55.287 + // Set them from contained ethhdr, or leave as received? 55.288 + // 'Ware use of hard_header_len in eth_type_trans(). 55.289 + 55.290 + //skb->protocol = htons(ETH_P_IP); 55.291 + 55.292 + if(ntohs(eth->h_proto) >= 1536){ 55.293 + skb->protocol = eth->h_proto; 55.294 + } else { 55.295 + skb->protocol = htons(ETH_P_802_2); 55.296 + } 55.297 + 55.298 + if(mac_is_multicast(eth->h_dest)){ 55.299 + if(mac_is_broadcast(eth->h_dest)){ 55.300 + skb->pkt_type = PACKET_BROADCAST; 55.301 + } else { 55.302 + skb->pkt_type = PACKET_MULTICAST; 55.303 + } 55.304 + } else { 55.305 + skb->pkt_type = PACKET_HOST; 55.306 + } 55.307 + 55.308 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); 55.309 + if (skb->ip_summed == CHECKSUM_HW){ 55.310 + skb->ip_summed = CHECKSUM_NONE; 55.311 + //skb->csum = csum_sub(skb->csum, 55.312 + // csum_partial(skb->mac.raw, skb->nh.raw - skb->mac.raw, 0)); 55.313 + } 55.314 + dst_release(skb->dst); 55.315 + skb->dst = NULL; 55.316 +#ifdef CONFIG_NETFILTER 55.317 + nf_conntrack_put(skb->nfct); 55.318 + skb->nfct = NULL; 55.319 +#ifdef CONFIG_NETFILTER_DEBUG 55.320 + skb->nf_debug = 0; 55.321 +#endif 55.322 +#endif 55.323 + } 55.324 + 55.325 + //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len + ETH_HLEN); 55.326 + 55.327 + err = vnet_skb_recv(skb, vnet, (Vmac*)MAC_ETH(skb)->h_dest); 55.328 + exit: 55.329 + if(mine) err = 1; 55.330 + dprintf("< skb=%p err=%d\n", skb, err); 55.331 + return err; 55.332 +} 55.333 + 55.334 +/** Handle an ICMP error related to etherip. 55.335 + * 55.336 + * @param skb ICMP error packet 55.337 + * @param info 55.338 + */ 55.339 +static void etherip_protocol_icmp_err(struct sk_buff *skb, u32 info){ 55.340 + struct iphdr *iph = (struct iphdr*)skb->data; 55.341 + 55.342 + wprintf("> ICMP error type=%d code=%d addr=" IPFMT "\n", 55.343 + skb->h.icmph->type, skb->h.icmph->code, NIPQUAD(iph->daddr)); 55.344 + 55.345 + if (skb->h.icmph->type != ICMP_DEST_UNREACH || 55.346 + skb->h.icmph->code != ICMP_FRAG_NEEDED){ 55.347 + return; 55.348 + } 55.349 + wprintf("> MTU too big addr= " IPFMT "\n", NIPQUAD(iph->daddr)); 55.350 +} 55.351 + 55.352 +//============================================================================ 55.353 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 55.354 +// Code for 2.6 kernel. 55.355 + 55.356 +/** Etherip protocol. */ 55.357 +static struct net_protocol etherip_protocol = { 55.358 + .handler = etherip_protocol_recv, 55.359 + .err_handler = etherip_protocol_icmp_err, 55.360 +}; 55.361 + 55.362 +static int etherip_protocol_add(void){ 55.363 + return inet_add_protocol(ðerip_protocol, IPPROTO_ETHERIP); 55.364 +} 55.365 + 55.366 +static int etherip_protocol_del(void){ 55.367 + return inet_del_protocol(ðerip_protocol, IPPROTO_ETHERIP); 55.368 +} 55.369 + 55.370 +//============================================================================ 55.371 +#else 55.372 +//============================================================================ 55.373 +// Code for 2.4 kernel. 55.374 + 55.375 +/** Etherip protocol. */ 55.376 +static struct inet_protocol etherip_protocol = { 55.377 + .name = "ETHERIP", 55.378 + .protocol = IPPROTO_ETHERIP, 55.379 + .handler = etherip_protocol_recv, 55.380 + .err_handler = etherip_protocol_icmp_err, 55.381 +}; 55.382 + 55.383 +static int etherip_protocol_add(void){ 55.384 + inet_add_protocol(ðerip_protocol); 55.385 + return 0; 55.386 +} 55.387 + 55.388 +static int etherip_protocol_del(void){ 55.389 + return inet_del_protocol(ðerip_protocol); 55.390 +} 55.391 + 55.392 +#endif 55.393 +//============================================================================ 55.394 + 55.395 + 55.396 +/** Initialize the etherip module. 55.397 + * Registers the etherip protocol. 55.398 + * 55.399 + * @return 0 on success, error code otherwise 55.400 + */ 55.401 +int __init etherip_module_init(void) { 55.402 + int err = 0; 55.403 + etherip_protocol_add(); 55.404 + return err; 55.405 +} 55.406 + 55.407 +/** Finalize the etherip module. 55.408 + * Deregisters the etherip protocol. 55.409 + */ 55.410 +void __exit etherip_module_exit(void) { 55.411 + if(etherip_protocol_del() < 0){ 55.412 + printk(KERN_INFO "%s: can't remove etherip protocol\n", __FUNCTION__); 55.413 + } 55.414 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 56.2 +++ b/tools/vnet/vnet-module/etherip.h Wed Nov 24 12:07:16 2004 +0000 56.3 @@ -0,0 +1,27 @@ 56.4 +/* 56.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 56.6 + * 56.7 + * This program is free software; you can redistribute it and/or modify 56.8 + * it under the terms of the GNU General Public License as published by the 56.9 + * Free Software Foundation; either version 2 of the License, or (at your 56.10 + * option) any later version. 56.11 + * 56.12 + * This program is distributed in the hope that it will be useful, but 56.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 56.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 56.15 + * for more details. 56.16 + * 56.17 + * You should have received a copy of the GNU General Public License along 56.18 + * with this program; if not, write to the Free software Foundation, Inc., 56.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA 56.20 + * 56.21 + */ 56.22 +#ifndef _VNET_ETHERIP_H_ 56.23 +#define _VNET_ETHERIP_H_ 56.24 + 56.25 +#include "if_etherip.h" 56.26 + 56.27 +extern int etherip_module_init(void); 56.28 +extern void etherip_module_exit(void); 56.29 + 56.30 +#endif