├── .clang-format ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── cfg ├── 2_fn_intra_node_bf3_dpu.cfg ├── 2_fn_intra_node_themis_host.cfg ├── example.cfg ├── example_mutli_node.cfg ├── motion-detection.cfg ├── online-boutique-concurrency-32.cfg ├── online-boutique-multi-nodes.cfg ├── parking.cfg └── test.cfg ├── docker ├── Dockerfile └── docker.sh ├── docs ├── 01-create-cluster-on-cloudlab.md ├── 02-upgrade-kernel-install-deps.md ├── 03-setup-k8s-kn.md ├── 04-setup-spright.md ├── ARTIFACTS.md ├── Docker.md ├── TROUBLESHOOTING.md └── USAGE.md ├── ebpf └── sk_msg_kern.c ├── go ├── go.mod ├── go.sum └── nf.go ├── meson.build ├── python ├── gateway.py ├── manifest │ └── test-function.yaml ├── nf.py └── shm_mgr.py ├── run.sh ├── scripts ├── conda_setup.sh ├── edit_cfg_cloudlab_hostname.py ├── example_nginx.conf ├── microbench │ ├── pipe_latency_multithreads.c │ └── pipe_latency_singlethread.c ├── run_once_multi_nodes_online_boutique.sh └── run_once_single_node_dummy_with_nginx.sh ├── sigcomm-experiment ├── env-setup │ ├── 001-env_setup_master.sh │ ├── 002-env_setup_master.sh │ ├── 100-docker_install.sh │ ├── 200-k8s_install.sh │ ├── 201-taint_nodes.sh │ ├── 300-knative_install.sh │ ├── 400-install_locust.sh │ └── 401-motion_dataset_download.sh ├── expt-1-online-boutique │ ├── consolidate_locust_stats.sh │ ├── hack │ │ └── hack.py │ ├── load-generator │ │ ├── README.md │ │ ├── kn-locustfile.py │ │ ├── requirements.in │ │ ├── requirements.txt │ │ └── spright-locustfile.py │ ├── manifests │ │ ├── dummuy-online-boutique │ │ │ ├── nginx.default.conf │ │ │ ├── online-boutique-proxy.yaml │ │ │ └── online-boutique.yaml │ │ ├── knative │ │ │ ├── adservice.yaml │ │ │ ├── cartservice.yaml │ │ │ ├── checkoutservice.yaml │ │ │ ├── currencyservice.yaml │ │ │ ├── emailservice.yaml │ │ │ ├── frontend.yaml │ │ │ ├── paymentservice.yaml │ │ │ ├── productcatalogservice.yaml │ │ │ ├── recommendationservice.yaml │ │ │ └── shippingservice.yaml │ │ └── kubernetes │ │ │ ├── adservice.yaml │ │ │ ├── cartservice.yaml │ │ │ ├── checkoutservice.yaml │ │ │ ├── currencyservice.yaml │ │ │ ├── emailservice.yaml │ │ │ ├── frontend.yaml │ │ │ ├── paymentservice.yaml │ │ │ ├── productcatalogservice.yaml │ │ │ ├── recommendationservice.yaml │ │ │ └── shippingservice.yaml │ ├── run_grpc.sh │ ├── run_kn.sh │ ├── run_load_generators.sh │ ├── run_spright.sh │ ├── set_fd.sh │ ├── set_tmux_master.sh │ └── set_tmux_worker.sh ├── expt-2-motion-detection │ ├── cfg │ │ ├── default.conf │ │ └── nginx.conf │ ├── hack │ │ └── hack.py │ ├── load-generator │ │ ├── README.md │ │ ├── kn-motion-generator.py │ │ └── spright-motion-generator.py │ ├── manifests │ │ ├── kn-motion-function-chain.yaml │ │ └── kn-motion-proxy.yaml │ ├── run_kn.sh │ ├── run_spright.sh │ └── set_tmux_master.sh └── expt-3-parking │ ├── cfg │ ├── default.conf │ └── nginx.conf │ ├── hack │ └── hack.py │ ├── load-generator │ ├── image.jpeg │ ├── kn-parking.py │ └── skmsg-parking.py │ ├── manifests │ ├── kn-parking-function-chain.yaml │ └── kn-parking-proxy.yaml │ ├── run_kn.sh │ ├── run_spright.sh │ └── set_tmux_master.sh └── src ├── common.c ├── cstl ├── Makefile ├── README.md ├── inc │ ├── c_algorithms.h │ ├── c_array.h │ ├── c_deque.h │ ├── c_errors.h │ ├── c_iterator.h │ ├── c_lib.h │ ├── c_map.h │ ├── c_rb.h │ ├── c_set.h │ └── c_slist.h ├── meson.build ├── src │ ├── Makefile │ ├── c_algorithms.c │ ├── c_array.c │ ├── c_deque.c │ ├── c_map.c │ ├── c_rb.c │ ├── c_set.c │ ├── c_slist.c │ └── c_util.c ├── test │ ├── Makefile │ ├── t_c_algorithms.c │ ├── t_c_array.c │ ├── t_c_deque.c │ ├── t_c_map.c │ ├── t_c_rb.c │ ├── t_c_set.c │ ├── t_c_slist.c │ └── t_clib.c └── win │ ├── clib.sln │ ├── clib.vcproj │ └── tclib.vcproj ├── gateway.c ├── include ├── common.h ├── http.h ├── io.h ├── shm_rpc.h ├── spright.h ├── timer.h └── utility.h ├── io_helper.c ├── io_rte_ring.c ├── io_sk_msg.c ├── log ├── log.c └── log.h ├── nf.c ├── online_boutique ├── adservice.c ├── cartservice.c ├── checkoutservice.c ├── currencyservice.c ├── emailservice.c ├── frontendservice.c ├── paymentservice.c ├── productcatalogservice.c ├── recommendationservice.c └── shippingservice.c ├── shm_mgr.c ├── shm_rpc.c ├── sockmap_manager.c ├── timer.c └── utility.c /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Microsoft 4 | AccessModifierOffset: -2 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveMacros: false 7 | AlignConsecutiveAssignments: false 8 | AlignConsecutiveDeclarations: false 9 | AlignEscapedNewlines: Right 10 | AlignOperands: true 11 | AlignTrailingComments: true 12 | AllowAllArgumentsOnNextLine: true 13 | AllowAllConstructorInitializersOnNextLine: true 14 | AllowAllParametersOfDeclarationOnNextLine: true 15 | AllowShortBlocksOnASingleLine: Never 16 | AllowShortCaseLabelsOnASingleLine: false 17 | AllowShortFunctionsOnASingleLine: None 18 | AllowShortLambdasOnASingleLine: All 19 | AllowShortIfStatementsOnASingleLine: Never 20 | AllowShortLoopsOnASingleLine: false 21 | AlwaysBreakAfterDefinitionReturnType: None 22 | AlwaysBreakAfterReturnType: None 23 | AlwaysBreakBeforeMultilineStrings: false 24 | AlwaysBreakTemplateDeclarations: MultiLine 25 | BinPackArguments: true 26 | BinPackParameters: true 27 | BraceWrapping: 28 | AfterCaseLabel: false 29 | AfterClass: true 30 | AfterControlStatement: true 31 | AfterEnum: true 32 | AfterFunction: true 33 | AfterNamespace: true 34 | AfterObjCDeclaration: true 35 | AfterStruct: true 36 | AfterUnion: false 37 | AfterExternBlock: true 38 | BeforeCatch: true 39 | BeforeElse: true 40 | IndentBraces: false 41 | SplitEmptyFunction: true 42 | SplitEmptyRecord: true 43 | SplitEmptyNamespace: true 44 | BreakBeforeBinaryOperators: None 45 | BreakBeforeBraces: Custom 46 | BreakBeforeInheritanceComma: false 47 | BreakInheritanceList: BeforeColon 48 | BreakBeforeTernaryOperators: true 49 | BreakConstructorInitializersBeforeComma: false 50 | BreakConstructorInitializers: BeforeColon 51 | BreakAfterJavaFieldAnnotations: false 52 | BreakStringLiterals: true 53 | ColumnLimit: 120 54 | CommentPragmas: '^ IWYU pragma:' 55 | CompactNamespaces: false 56 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 57 | ConstructorInitializerIndentWidth: 4 58 | ContinuationIndentWidth: 4 59 | Cpp11BracedListStyle: true 60 | DeriveLineEnding: true 61 | DerivePointerAlignment: false 62 | DisableFormat: false 63 | ExperimentalAutoDetectBinPacking: false 64 | FixNamespaceComments: true 65 | ForEachMacros: 66 | - foreach 67 | - Q_FOREACH 68 | - BOOST_FOREACH 69 | IncludeBlocks: Preserve 70 | IncludeCategories: 71 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 72 | Priority: 2 73 | SortPriority: 0 74 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 75 | Priority: 3 76 | SortPriority: 0 77 | - Regex: '.*' 78 | Priority: 1 79 | SortPriority: 0 80 | IncludeIsMainRegex: '(Test)?$' 81 | IncludeIsMainSourceRegex: '' 82 | IndentCaseLabels: false 83 | IndentGotoLabels: true 84 | IndentPPDirectives: None 85 | IndentWidth: 4 86 | IndentWrappedFunctionNames: false 87 | JavaScriptQuotes: Leave 88 | JavaScriptWrapImports: true 89 | KeepEmptyLinesAtTheStartOfBlocks: true 90 | MacroBlockBegin: '' 91 | MacroBlockEnd: '' 92 | MaxEmptyLinesToKeep: 1 93 | NamespaceIndentation: None 94 | ObjCBinPackProtocolList: Auto 95 | ObjCBlockIndentWidth: 2 96 | ObjCSpaceAfterProperty: false 97 | ObjCSpaceBeforeProtocolList: true 98 | PenaltyBreakAssignment: 2 99 | PenaltyBreakBeforeFirstCallParameter: 19 100 | PenaltyBreakComment: 300 101 | PenaltyBreakFirstLessLess: 120 102 | PenaltyBreakString: 1000 103 | PenaltyBreakTemplateDeclaration: 10 104 | PenaltyExcessCharacter: 1000000 105 | PenaltyReturnTypeOnItsOwnLine: 1000 106 | PointerAlignment: Right 107 | ReflowComments: true 108 | SortIncludes: true 109 | SortUsingDeclarations: true 110 | SpaceAfterCStyleCast: false 111 | SpaceAfterLogicalNot: false 112 | SpaceAfterTemplateKeyword: true 113 | SpaceBeforeAssignmentOperators: true 114 | SpaceBeforeCpp11BracedList: false 115 | SpaceBeforeCtorInitializerColon: true 116 | SpaceBeforeInheritanceColon: true 117 | SpaceBeforeParens: ControlStatements 118 | SpaceBeforeRangeBasedForLoopColon: true 119 | SpaceInEmptyBlock: false 120 | SpaceInEmptyParentheses: false 121 | SpacesBeforeTrailingComments: 1 122 | SpacesInAngles: false 123 | SpacesInConditionalStatement: false 124 | SpacesInContainerLiterals: true 125 | SpacesInCStyleCastParentheses: false 126 | SpacesInParentheses: false 127 | SpacesInSquareBrackets: false 128 | SpaceBeforeSquareBrackets: false 129 | Standard: Latest 130 | StatementMacros: 131 | - Q_UNUSED 132 | - QT_REQUIRE_VERSION 133 | TabWidth: 4 134 | UseCRLF: false 135 | UseTab: Never 136 | ... 137 | 138 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | bin 3 | src/*.o 4 | src/*.d 5 | src/**/*.o 6 | src/**/*.d 7 | src/cstl/test 8 | src/cstl/**/*.a 9 | 10 | # idea files 11 | .DS_Store 12 | .idea 13 | nodes_name.txt 14 | 15 | # VS code files 16 | .vscode 17 | 18 | # python 19 | *.pyc 20 | __pycache__ 21 | 22 | # helm dependencies 23 | charts 24 | requirements.lock 25 | 26 | # Object and binary from SPRIGHT 27 | ebpf/*.o 28 | 29 | # cfg backup files 30 | cfg/*.bak -------------------------------------------------------------------------------- /cfg/2_fn_intra_node_bf3_dpu.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2022 University of California, Riverside 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name = "2 Fn Example (Single Node on BF3 DPU)"; 18 | 19 | nfs = ( 20 | { 21 | id = 1; 22 | name = "NF 1"; 23 | 24 | n_threads = 2; 25 | 26 | params = { 27 | memory_mb = 1; 28 | sleep_ns = 15; 29 | compute = 1000; 30 | }; 31 | 32 | node = 0; 33 | }, 34 | { 35 | id = 2; 36 | name = "NF 2"; 37 | 38 | n_threads = 1; 39 | 40 | params = { 41 | memory_mb = 2; 42 | sleep_ns = 20; 43 | compute = 500; 44 | }; 45 | 46 | node = 0; 47 | } 48 | ); 49 | 50 | routes = ( 51 | { 52 | id = 1; 53 | name = "Route 1"; 54 | 55 | hops = [1, 2]; 56 | } 57 | ); 58 | 59 | nodes = ( 60 | { 61 | id = 0; 62 | hostname = "localhost.localdomain"; 63 | 64 | ip_address = "10.93.231.112"; 65 | port = 8083; 66 | }, 67 | { 68 | id = 1; 69 | hostname = "localhost.localdomain"; 70 | 71 | ip_address = "10.93.231.124"; 72 | port = 8083; 73 | } 74 | ); 75 | 76 | tenants = ( 77 | { 78 | id = 0; 79 | weight = 5; 80 | }, 81 | { 82 | id = 1; 83 | weight = 1; 84 | }, 85 | { 86 | id = 2; 87 | weight = 3; 88 | } 89 | ); 90 | -------------------------------------------------------------------------------- /cfg/2_fn_intra_node_themis_host.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2022 University of California, Riverside 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name = "2 Fn Example (Single Node on Host)"; 18 | 19 | nfs = ( 20 | { 21 | id = 1; 22 | name = "NF 1"; 23 | 24 | n_threads = 2; 25 | 26 | params = { 27 | memory_mb = 1; 28 | sleep_ns = 15; 29 | compute = 1000; 30 | }; 31 | 32 | node = 1; 33 | }, 34 | { 35 | id = 2; 36 | name = "NF 2"; 37 | 38 | n_threads = 1; 39 | 40 | params = { 41 | memory_mb = 2; 42 | sleep_ns = 20; 43 | compute = 500; 44 | }; 45 | 46 | node = 1; 47 | } 48 | ); 49 | 50 | routes = ( 51 | { 52 | id = 1; 53 | name = "Route 1"; 54 | 55 | hops = [1, 2]; 56 | } 57 | ); 58 | 59 | nodes = ( 60 | { 61 | id = 0; 62 | hostname = "themis"; 63 | 64 | ip_address = "10.93.231.113"; 65 | port = 8083; 66 | }, 67 | { 68 | id = 1; 69 | hostname = "themis-2"; 70 | 71 | ip_address = "10.93.231.121"; 72 | port = 8083; 73 | } 74 | ); 75 | 76 | tenants = ( 77 | { 78 | id = 0; 79 | weight = 5; 80 | }, 81 | { 82 | id = 1; 83 | weight = 1; 84 | }, 85 | { 86 | id = 2; 87 | weight = 3; 88 | } 89 | ); 90 | -------------------------------------------------------------------------------- /cfg/example.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2022 University of California, Riverside 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name = "Example (Single Node)"; 18 | 19 | nfs = ( 20 | { 21 | id = 1; 22 | name = "NF 1"; 23 | 24 | n_threads = 2; 25 | 26 | params = { 27 | memory_mb = 1; 28 | sleep_ns = 15; 29 | compute = 1000; 30 | }; 31 | 32 | node = 0; 33 | }, 34 | { 35 | id = 2; 36 | name = "NF 2"; 37 | 38 | n_threads = 1; 39 | 40 | params = { 41 | memory_mb = 2; 42 | sleep_ns = 20; 43 | compute = 500; 44 | }; 45 | 46 | node = 0; 47 | }, 48 | { 49 | id = 3; 50 | name = "NF 3"; 51 | 52 | n_threads = 8; 53 | 54 | params = { 55 | memory_mb = 3; 56 | sleep_ns = 5; 57 | compute = 250; 58 | }; 59 | 60 | node = 0; 61 | }, 62 | { 63 | id = 4; 64 | name = "NF 4"; 65 | 66 | n_threads = 4; 67 | 68 | params = { 69 | memory_mb = 4; 70 | sleep_ns = 10; 71 | compute = 125; 72 | }; 73 | 74 | node = 0; 75 | } 76 | ); 77 | 78 | routes = ( 79 | { 80 | id = 1; 81 | name = "Route 1"; 82 | 83 | hops = [1, 2, 3, 4, 1]; 84 | }, 85 | { 86 | id = 2; 87 | name = "Route 2"; 88 | 89 | hops = [1, 0, 2, 0, 3, 0, 4, 1]; 90 | }, 91 | { 92 | id = 3; 93 | name = "Route 3"; 94 | 95 | hops = [1, 2, 3]; 96 | }, 97 | { 98 | id = 4; 99 | name = "Route 4"; 100 | 101 | hops = [1, 0, 2, 0, 3, 0, 4, 0, 3, 0, 2, 0, 1]; 102 | } 103 | ); 104 | 105 | nodes = ( 106 | { 107 | id = 0; 108 | hostname = "node0.spright.kkprojects-pg0.wisc.cloudlab.us"; 109 | 110 | ip_address = "10.10.1.1"; 111 | port = 8083; 112 | }, 113 | { 114 | id = 1; 115 | hostname = "node1.spright.kkprojects-pg0.wisc.cloudlab.us"; 116 | 117 | ip_address = "10.10.1.2"; 118 | port = 8083; 119 | } 120 | ); 121 | 122 | tenants = ( 123 | { 124 | id = 0; 125 | weight = 5; 126 | }, 127 | { 128 | id = 1; 129 | weight = 1; 130 | }, 131 | { 132 | id = 2; 133 | weight = 3; 134 | } 135 | ); -------------------------------------------------------------------------------- /cfg/example_mutli_node.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2022 University of California, Riverside 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name = "Example (Two Nodes)"; 18 | 19 | nfs = ( 20 | { 21 | id = 1; 22 | name = "NF 1"; 23 | 24 | n_threads = 2; 25 | 26 | params = { 27 | memory_mb = 1; 28 | sleep_ns = 15; 29 | compute = 1000; 30 | }; 31 | 32 | node = 0; 33 | }, 34 | { 35 | id = 2; 36 | name = "NF 2"; 37 | 38 | n_threads = 1; 39 | 40 | params = { 41 | memory_mb = 2; 42 | sleep_ns = 20; 43 | compute = 500; 44 | }; 45 | 46 | node = 0; 47 | }, 48 | { 49 | id = 3; 50 | name = "NF 3"; 51 | 52 | n_threads = 8; 53 | 54 | params = { 55 | memory_mb = 3; 56 | sleep_ns = 5; 57 | compute = 250; 58 | }; 59 | 60 | node = 0; 61 | }, 62 | { 63 | id = 4; 64 | name = "NF 4"; 65 | 66 | n_threads = 4; 67 | 68 | params = { 69 | memory_mb = 4; 70 | sleep_ns = 10; 71 | compute = 125; 72 | }; 73 | 74 | node = 1; 75 | } 76 | ); 77 | 78 | routes = ( 79 | { 80 | id = 1; 81 | name = "Route 1"; 82 | 83 | hops = [1, 2, 3, 4, 1]; 84 | }, 85 | { 86 | id = 2; 87 | name = "Route 2"; 88 | 89 | hops = [1, 0, 2, 0, 3, 0, 4, 1]; 90 | }, 91 | { 92 | id = 3; 93 | name = "Route 3"; 94 | 95 | hops = [1, 2, 3]; 96 | }, 97 | { 98 | id = 4; 99 | name = "Route 4"; 100 | 101 | hops = [1, 0, 2, 0, 3, 0, 4, 0, 3, 0, 2, 0, 1]; 102 | } 103 | ); 104 | 105 | nodes = ( 106 | { 107 | id = 0; 108 | hostname = "node0.spright.kkprojects-pg0.wisc.cloudlab.us"; 109 | 110 | ip_address = "10.10.1.1"; 111 | port = 8083; 112 | }, 113 | { 114 | id = 1; 115 | hostname = "node1.spright.kkprojects-pg0.wisc.cloudlab.us"; 116 | 117 | ip_address = "10.10.1.2"; 118 | port = 8083; 119 | } 120 | ); 121 | 122 | tenants = ( 123 | { 124 | id = 0; 125 | weight = 5; 126 | }, 127 | { 128 | id = 1; 129 | weight = 1; 130 | }, 131 | { 132 | id = 2; 133 | weight = 3; 134 | } 135 | ); -------------------------------------------------------------------------------- /cfg/motion-detection.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2022 University of California, Riverside 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name = "Motion Detection"; 18 | 19 | nfs = ( 20 | { 21 | id = 1; 22 | name = "Sensor"; 23 | 24 | n_threads = 32; 25 | 26 | params = { 27 | memory_mb = 0; 28 | sleep_ns = 1000; 29 | compute = 0; 30 | }; 31 | }, 32 | { 33 | id = 2; 34 | name = "Actuator"; 35 | 36 | n_threads = 32; 37 | 38 | params = { 39 | memory_mb = 0; 40 | sleep_ns = 1000; 41 | compute = 0; 42 | }; 43 | } 44 | ); 45 | 46 | routes = ( 47 | { 48 | id = 1; 49 | name = "Route 1"; 50 | 51 | hops = [1, 2]; 52 | } 53 | ); 54 | -------------------------------------------------------------------------------- /cfg/online-boutique-concurrency-32.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2022 University of California, Riverside 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name = "Online Boutique (Single Node)"; 18 | 19 | nfs = ( 20 | { 21 | id = 1; 22 | name = "frontendservice"; 23 | 24 | n_threads = 32; 25 | 26 | params = { 27 | memory_mb = 0; 28 | sleep_ns = 0; 29 | compute = 0; 30 | }; 31 | 32 | node = 0; 33 | }, 34 | { 35 | id = 2; 36 | name = "currencyservice"; 37 | 38 | n_threads = 32; 39 | 40 | params = { 41 | memory_mb = 0; 42 | sleep_ns = 0; 43 | compute = 0; 44 | }; 45 | 46 | node = 0; 47 | }, 48 | { 49 | id = 3; 50 | name = "productcatalogservice"; 51 | 52 | n_threads = 32; 53 | 54 | params = { 55 | memory_mb = 0; 56 | sleep_ns = 0; 57 | compute = 0; 58 | }; 59 | 60 | node = 0; 61 | }, 62 | { 63 | id = 4; 64 | name = "cartservice"; 65 | 66 | n_threads = 32; 67 | 68 | params = { 69 | memory_mb = 0; 70 | sleep_ns = 0; 71 | compute = 0; 72 | }; 73 | 74 | node = 0; 75 | }, 76 | { 77 | id = 5; 78 | name = "recommendationservice"; 79 | 80 | n_threads = 32; 81 | 82 | params = { 83 | memory_mb = 0; 84 | sleep_ns = 0; 85 | compute = 0; 86 | }; 87 | 88 | node = 0; 89 | }, 90 | { 91 | id = 6; 92 | name = "shippingservice"; 93 | 94 | n_threads = 32; 95 | 96 | params = { 97 | memory_mb = 0; 98 | sleep_ns = 0; 99 | compute = 0; 100 | }; 101 | 102 | node = 0; 103 | }, 104 | { 105 | id = 7; 106 | name = "checkoutservice"; 107 | 108 | n_threads = 32; 109 | 110 | params = { 111 | memory_mb = 0; 112 | sleep_ns = 0; 113 | compute = 0; 114 | }; 115 | 116 | node = 0; 117 | }, 118 | { 119 | id = 8; 120 | name = "paymentservice"; 121 | 122 | n_threads = 32; 123 | 124 | params = { 125 | memory_mb = 0; 126 | sleep_ns = 0; 127 | compute = 0; 128 | }; 129 | 130 | node = 0; 131 | }, 132 | { 133 | id = 9; 134 | name = "emailservice"; 135 | 136 | n_threads = 32; 137 | 138 | params = { 139 | memory_mb = 0; 140 | sleep_ns = 0; 141 | compute = 0; 142 | }; 143 | 144 | node = 0; 145 | }, 146 | { 147 | id = 10; 148 | name = "adservice"; 149 | 150 | n_threads = 32; 151 | 152 | params = { 153 | memory_mb = 0; 154 | sleep_ns = 0; 155 | compute = 0; 156 | }; 157 | 158 | node = 0; 159 | } 160 | ); 161 | 162 | routes = ( 163 | { 164 | id = 1; 165 | name = "GET /"; 166 | 167 | hops = [1, 2, 1, 3, 1, 4, 1, 2, 1, 10, 1]; 168 | }, 169 | { 170 | id = 2; 171 | name = "POST /setCurrency"; 172 | 173 | hops = [1]; 174 | }, 175 | { 176 | id = 3; 177 | name = "GET /product/$ID"; 178 | 179 | hops = [1, 3, 1, 2, 1, 4, 1, 2, 1, 5, 1, 4, 1, 10, 1]; 180 | }, 181 | { 182 | id = 4; 183 | name = "GET /cart"; 184 | 185 | hops = [1, 2, 1, 4, 1, 5, 1, 6, 1, 2, 1, 3, 1, 2, 1]; 186 | }, 187 | { 188 | id = 5; 189 | name = "POST /cart"; 190 | 191 | hops = [1, 3, 1, 4, 1]; 192 | }, 193 | { 194 | id = 6; 195 | name = "POST /cart/checkout"; 196 | 197 | hops = [1, 7, 4, 7, 3, 7, 2, 7, 6, 7, 2, 7, 8, 7, 6, 7, 4, 7, 9, 7, 1, 5, 1, 2, 1]; 198 | } 199 | ); 200 | 201 | nodes = ( 202 | { 203 | id = 0; 204 | hostname = "node0.spright.kkprojects-pg0.wisc.cloudlab.us"; 205 | 206 | ip_address = "10.10.1.1"; 207 | port = 8083; 208 | } 209 | ); -------------------------------------------------------------------------------- /cfg/parking.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2022 University of California, Riverside 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name = "Motion Detection"; 18 | 19 | nfs = ( 20 | { 21 | id = 1; 22 | name = "Detection"; 23 | 24 | n_threads = 32; 25 | 26 | params = { 27 | memory_mb = 0; 28 | sleep_ns = 435000000; 29 | compute = 0; 30 | }; 31 | }, 32 | { 33 | id = 2; 34 | name = "Search"; 35 | 36 | n_threads = 32; 37 | 38 | params = { 39 | memory_mb = 0; 40 | sleep_ns = 20000000; 41 | compute = 0; 42 | }; 43 | }, 44 | { 45 | id = 3; 46 | name = "Index"; 47 | 48 | n_threads = 32; 49 | 50 | params = { 51 | memory_mb = 0; 52 | sleep_ns = 1000000; 53 | compute = 0; 54 | }; 55 | }, 56 | { 57 | id = 4; 58 | name = "Charging"; 59 | 60 | n_threads = 32; 61 | 62 | params = { 63 | memory_mb = 0; 64 | sleep_ns = 50000000; 65 | compute = 0; 66 | }; 67 | }, 68 | { 69 | id = 5; 70 | name = "Persist"; 71 | 72 | n_threads = 32; 73 | 74 | params = { 75 | memory_mb = 0; 76 | sleep_ns = 10000000; 77 | compute = 0; 78 | }; 79 | } 80 | ); 81 | 82 | routes = ( 83 | { 84 | id = 1; 85 | name = "Route 1"; 86 | 87 | hops = [1, 2, 3, 5, 4]; 88 | }, 89 | { 90 | id = 2; 91 | name = "Route 2"; 92 | 93 | hops = [1, 2, 4]; 94 | } 95 | ); 96 | -------------------------------------------------------------------------------- /cfg/test.cfg: -------------------------------------------------------------------------------- 1 | # Copyright 2022 University of California, Riverside 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | name = "Example"; 18 | 19 | nfs = ( 20 | { 21 | id = 1; 22 | name = "NF 1"; 23 | 24 | n_threads = 1; 25 | 26 | params = { 27 | memory_mb = 0; 28 | sleep_ns = 0; 29 | compute = 0; 30 | }; 31 | }, 32 | { 33 | id = 2; 34 | name = "NF 2"; 35 | 36 | n_threads = 1; 37 | 38 | params = { 39 | memory_mb = 0; 40 | sleep_ns = 0; 41 | compute = 0; 42 | }; 43 | }, 44 | { 45 | id = 3; 46 | name = "NF 3"; 47 | 48 | n_threads = 1; 49 | 50 | params = { 51 | memory_mb = 0; 52 | sleep_ns = 0; 53 | compute = 0; 54 | }; 55 | }, 56 | { 57 | id = 4; 58 | name = "NF 4"; 59 | 60 | n_threads = 1; 61 | 62 | params = { 63 | memory_mb = 0; 64 | sleep_ns = 0; 65 | compute = 0; 66 | }; 67 | } 68 | ); 69 | 70 | routes = ( 71 | { 72 | id = 1; 73 | name = "Route 1"; 74 | 75 | hops = [1, 2, 3, 4]; 76 | }, 77 | { 78 | id = 2; 79 | name = "Route 2"; 80 | 81 | hops = [1, 0, 2, 0, 3, 0, 4]; 82 | }, 83 | { 84 | id = 3; 85 | name = "Route 3"; 86 | 87 | hops = [1, 2, 3, 4, 3, 2, 1]; 88 | }, 89 | { 90 | id = 4; 91 | name = "Route 4"; 92 | 93 | hops = [1, 0, 2, 0, 3, 0, 4, 0, 3, 0, 2, 0, 1]; 94 | } 95 | ); 96 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use Ubuntu 20.04 as the base image, as specified in the YAML 2 | FROM ubuntu:20.04 3 | 4 | # Ubuntu 20.04 image hangs unless timezone is set 5 | RUN DEBIAN_FRONTEND=noninteractive \ 6 | ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime 7 | 8 | # Install any necessary dependencies 9 | RUN apt-get update && \ 10 | apt-get install -y \ 11 | libelf-dev \ 12 | libpcap-dev \ 13 | libnuma-dev \ 14 | libconfig-dev \ 15 | dpdk-dev \ 16 | pkg-config \ 17 | iproute2 18 | 19 | # Set up working directory for SPRIGHT 20 | WORKDIR /mydata/spright 21 | 22 | # Keep the container running 23 | CMD ["bash", "-c", "while true; do sleep 30; done;"] 24 | -------------------------------------------------------------------------------- /docker/docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | IMAGE_NAME=$1 4 | CONTAINER_NAME=$2 5 | 6 | sudo docker run -d \ 7 | --name $CONTAINER_NAME \ 8 | --privileged \ 9 | --network bridge \ 10 | --device=/dev/net/tun \ 11 | --device=/dev/uio0 \ 12 | -v /dev/hugepages:/dev/hugepages \ 13 | -v /var/run/dpdk:/var/run/dpdk \ 14 | -v /lib/x86_64-linux-gnu:/lib/x86_64-linux-gnu \ 15 | -v /usr/local/lib/x86_64-linux-gnu:/usr/local/lib/x86_64-linux-gnu \ 16 | -v /usr/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu \ 17 | -v /usr/lib64:/usr/lib64 \ 18 | -v /mydata/spright:/mydata/spright \ 19 | $IMAGE_NAME 20 | -------------------------------------------------------------------------------- /docs/01-create-cluster-on-cloudlab.md: -------------------------------------------------------------------------------- 1 | # Creating a 2-node cluster on Cloudlab 2 | This guideline is mainly for creating a cluster on NSF Cloudlab. We have tested several physical node types on NSF Cloudlab, such as [xl170](https://www.utah.cloudlab.us/portal/show-nodetype.php?type=xl170) and [c220g5](https://www.wisc.cloudlab.us/portal/show-nodetype.php?type=c220g5), but it should work on any **x86** nodes on NSF Cloudlab. Please refer to [The Cloud Lab Manual](http://docs.cloudlab.us/hardware.html) to find available node types on NSF Cloudlab and their hardware spec. 3 | - Note: We haven't tested SPRIGHT on any **arm** nodes yet, e.g., [m400](https://www.utah.cloudlab.us/portal/show-nodetype.php?type=m400). 4 | 5 | We conduct the experiment on **Ubuntu 20.04**. Using other Ubuntu distributions may lead to unexpect issues. We haven't fully verified this yet. 6 | 7 | ### Disk space on Cloudlab machines ### 8 | As Cloudlab only allocates 16GB disk space by default, please check **Temp Filesystem Max Space** to maximize the disk space configuration and keep **Temporary Filesystem Mount Point** as default (**/mydata**) 9 | 10 | ### Guideline ### 11 | 1. The following steps require a **bash** environment on Cloudlab. Please configure the default shell in your CloudLab account to be bash. For how to configure bash on Cloudlab, Please refer to the post "Choose your shell": https://www.cloudlab.us/portal-news.php?idx=49 12 | 13 | 2. When starting a new experiment on Cloudlab, select the **small-lan** profile 14 | 15 | 3. On the profile parameterization page, 16 | - Set **Number of Nodes** as needed 17 | - We use *node-0* as the master node to run the control plane of Kubernetes, Knative. 18 | - *node-1* is used as worker nodes. 19 | - Set OS image as **Ubuntu 20.04** 20 | - Set physical node type as **c220g5** (or any other preferred node type) 21 | - Please check **Temp Filesystem Max Space** box 22 | - Keep **Temporary Filesystem Mount Point** as default (**/mydata**) 23 | 24 | 4. Wait for the cluster to be initialized (It may take 5 to 10 minutes) 25 | 26 | --- 27 | 28 | 5. Extend the disk space on allocated master and worker nodes. This is because Cloudlab only allocates a 16GB disk space. 29 | - We use `/mydata` as the working directory 30 | - On the master node and worker nodes, run 31 | ```bash 32 | sudo chown -R $(id -u):$(id -g) /mydata 33 | cd /mydata 34 | export MYMOUNT=/mydata 35 | ``` -------------------------------------------------------------------------------- /docs/02-upgrade-kernel-install-deps.md: -------------------------------------------------------------------------------- 1 | ## Upgrading kernel & installing SPRIGHT dependencies on the master node (**node-0**) 2 | This guideline is for upgrading kernel and installing SPRIGHT dependencies (libbpf, DPDK RTE lib, ...) on the master node (**node-0**). 3 | 4 | We will run SPRIGHT functions on the master node and run the load generator ([Locust](https://locust.io/)) on the worker node 5 | - Note: It can also be done reversely, i.e., running SPRIGHT functions on the worker node and load generator on master node. Or even having a two worker node setup, and running SPRIGHT functions and load generator on different worker nodes. 6 | 7 | ### Update Kernel of the master node 8 | ```bash 9 | $ cd /mydata/spright 10 | 11 | spright$ ./sigcomm-experiment/env-setup/001-env_setup_master.sh 12 | 13 | # The master node will be rebooted after the script is complete 14 | # Rebooting usually takes 5 - 10 minutes 15 | ``` 16 | 17 | ### Re-login to master node after rebooting (**node-0**) 18 | 19 | ### Install libbpf, dpdk and SPRIGHT 20 | ```bash 21 | $ cd /mydata/spright 22 | 23 | spright$ ./sigcomm-experiment/env-setup/002-env_setup_master.sh 24 | ``` -------------------------------------------------------------------------------- /docs/03-setup-k8s-kn.md: -------------------------------------------------------------------------------- 1 | # Setting up Kubernetes & Knative 2 | 3 | ### 1 - Setting up the Kubernetes master node (**node-0**). 4 | ```shell= 5 | $ cd /mydata/spright 6 | 7 | spright$ export MYMOUNT=/mydata 8 | 9 | spright$ ./sigcomm-experiment/env-setup/100-docker_install.sh 10 | 11 | spright$ source ~/.bashrc 12 | 13 | spright$ ./sigcomm-experiment/env-setup/200-k8s_install.sh master 10.10.1.1 14 | 15 | ## Once the installation of Kuberentes control plane is done, 16 | ## it will print out an token `kubeadm join ...`. 17 | ## **PLEASE copy and save this token somewhere**. 18 | ## The worker node (**node-1**) needs this token to join the Kuberentes control plane. 19 | 20 | spright$ echo 'source <(kubectl completion bash)' >>~/.bashrc && source ~/.bashrc 21 | ``` 22 | 23 | ### 2 - Setting up the Kubernetes worker node (**node-1**). 24 | ```shell= 25 | $ cd /mydata/spright 26 | 27 | spright$ export MYMOUNT=/mydata 28 | 29 | spright$ ./sigcomm-experiment/env-setup/100-docker_install.sh 30 | 31 | spright$ source ~/.bashrc 32 | 33 | spright$ ./sigcomm-experiment/env-setup/200-k8s_install.sh slave 34 | 35 | # Use the token returned from the master node (**node-0**) to join the Kubernetes control plane. Run `sudo kubeadm join ...` with the token just saved. Please run the `kubeadm join` command with *sudo* 36 | spright$ sudo kubeadm join 37 | ``` 38 | 39 | ### 3 - Enable pod placement on master node (**node-0**) and taint worker node (**node-1**): 40 | ```shell= 41 | $ cd /mydata/spright 42 | spright$ ./sigcomm-experiment/env-setup/201-taint_nodes.sh 43 | ``` 44 | 45 | ### 4 - Setting up the Knative. 46 | 1. On the master node (**node-0**), run 47 | ```shell= 48 | $ cd /mydata/spright 49 | spright$ ./sigcomm-experiment/env-setup/300-knative_install.sh 50 | ``` -------------------------------------------------------------------------------- /docs/04-setup-spright.md: -------------------------------------------------------------------------------- 1 | # Setup SPRIGHT 2 | 3 | TODO-1: POBM, K8S, Kn Deployment 4 | 5 | TODO-2: Compile SPRIGHT binary 6 | 7 | TODO-3: build SPRIGHT docker image 8 | 9 | TODO-4: Explaim how to modify yaml file, env, volume mount, etc 10 | 11 | TODO-5: Add helm chart support 12 | 13 | ## Misc. 14 | ### Compile the eBPF code into an object file 15 | ```bash 16 | cd ebpf/ 17 | clang -g -O2 -c -target bpf -o sk_msg_kern.o sk_msg_kern.c 18 | 19 | # Copy sk_msg_kern.o to obj/ 20 | cp sk_msg_kern.o ../obj/ 21 | 22 | # Debugging purpose: output bpf_printk() 23 | sudo cat /sys/kernel/debug/tracing/trace_pipe 24 | ``` -------------------------------------------------------------------------------- /docs/Docker.md: -------------------------------------------------------------------------------- 1 | # Running SPRIGHT in Docker 2 | 3 | # TODOs 4 | 5 | 1. Move the build and installation of SPRIGHT dependencies (e.g., `dpdk`, `libbpf`) inside the Docker image to avoid host dependency setup. 6 | 2. Automate `.cfg` file configuration to dynamically set `hostname` and `ip_address` for components that need it. 7 | 3. Automate value initialization of `addr.sin_addr.s_addr` in `io_sk_msg.c` 8 | 4. Ensure all SPRIGHT containers operate in different namespaces to enable inter-component communication. 9 | -------------------------------------------------------------------------------- /docs/TROUBLESHOOTING.md: -------------------------------------------------------------------------------- 1 | ## Troubleshooting 2 | 3 | 1. When you run any SPRIGHT component, you got 4 | ``` 5 | error while loading shared libraries: libbpf.so.0: cannot open shared object file: No such file or directory 6 | ``` 7 | 8 | Solutions: This may happen when you use Ubuntu 22.04, which has the libbpf 0.5.0 pre-installed. You need to re-link the `/lib/x86_64-linux-gnu/libbpf.so.0` to `libbpf.so.0.6.0` 9 | ```bash 10 | # Assume you have executed the libbpf installation script 11 | cd /path/to/your/directory/of/libbpf/src 12 | 13 | # Copy libbpf.so.0.6.0 to /lib/x86_64-linux-gnu/ 14 | sudo cp libbpf.so.0.6.0 /lib/x86_64-linux-gnu/ 15 | 16 | # Re-link libbpf.so.0 17 | sudo ln -sf /lib/x86_64-linux-gnu/libbpf.so.0.6.0 /lib/x86_64-linux-gnu/libbpf.so.0 18 | ``` 19 | 20 | If you are working on arm64 platforms: 21 | ```bash 22 | # Assume you have executed the libbpf installation script 23 | cd /path/to/your/directory/of/libbpf/src 24 | 25 | sudo cp libbpf.so.0.6.0 /lib/aarch64-linux-gnu/ 26 | 27 | sudo ln -sf /lib/aarch64-linux-gnu/libbpf.so.0.6.0 /lib/aarch64-linux-gnu/libbpf.so.0 28 | ``` 29 | 30 | 2. If you want to run SPRIGHT on NVIDIA Bluefield-3 DPU (arm64), you may encounter `asm/types.h` error during compilation of libbpf. 31 | To solve this error, you need to symlink the `/usr/include/asm` directory: 32 | ```bash 33 | sudo ln -s /usr/include/aarch64-linux-gnu/asm/ /usr/include/asm 34 | ``` -------------------------------------------------------------------------------- /docs/USAGE.md: -------------------------------------------------------------------------------- 1 | ## SPRIGHT: Process-on-bare-metal (POBM) mode 2 | 3 | This guideline is mainly for deploying SPRIGHT as Processes-on-bare-metal, which can ease the development and testing. 4 | 5 | SPRIGHT supports two distinct operating modes, including the DPDK RTE RING mode (called D-SPRIGHT) and the SK_MSG model (called S-SPRIGHT). D-SPRIGHT depends on DPDK's [RTE RING](https://doc.dpdk.org/guides/prog_guide/ring_lib.html) to support descriptor delivery within the data plane, while S-SPRIGHT uses eBPF's SK_MSG to support descriptor delivery. 6 | 7 | Both use the same shared memory backend provided by DPDK's [MEMPOOL library](https://doc.dpdk.org/guides/prog_guide/mempool_lib.html). Although SPRIGHT could work with other shared memory backends, such as POSIX shared memory in Linux, we chose DPDK's shared memory for various performance reasons. For a detailed comparison of DPDK's shared memory and POSIX shared memory, see the [following link](https://www.dpdk.org/blog/2019/08/21/memory-in-dpdk-part-1-general-concepts/). 8 | 9 | We list the commands used to run the D-SPRIGHT. To run S-SPRIGHT, simply remove the `RTE_RING=1` from the D-SPRIGHT's commands. 10 | 11 | **NOTE: make sure you are under the root directory of SPRIGHT, where the `run.sh` locates** 12 | 13 | To start up the SPRIGHT's shared memory data plane, we first need to start up the shared memory manager, which is responsible for initializing the shared memory pool and buffers. We also need to input a configuration file of the function chain (`*.cfg`) to the shared memory manager. The configuration file defines the number of functions and the routes within the chain. 14 | ```shell= 15 | # I use the example.cfg, which defined 4 dummy functions 16 | sudo RTE_RING=1 ./run.sh shm_mgr cfg/example.cfg 17 | ``` 18 | 19 | Next, we need to bring up the SPRIGHT gateway that coordinates between the external clients and the backend SPRIGHT functions 20 | ```shell= 21 | sudo RTE_RING=1 ./run.sh gateway 22 | ``` 23 | 24 | We then need to start up SPRIGHT functions. Since the `example.cfg` specifies 4 functions, we need to create 4 functions. 25 | ```shell= 26 | # You may need to have multiple terminals 27 | # Run each function in a different terminals or use tmux 28 | # USAGE: sudo RTE_RING=1 ./run.sh nf 29 | 30 | # Remember to use the function id specified in the `example.cfg` 31 | 32 | # Terminal 1 33 | sudo RTE_RING=1 ./run.sh nf 1 34 | 35 | # Terminal 2 36 | sudo RTE_RING=1 ./run.sh nf 2 37 | 38 | # Terminal 3 39 | sudo RTE_RING=1 ./run.sh nf 3 40 | 41 | # Terminal 4 42 | sudo RTE_RING=1 ./run.sh nf 4 43 | ``` 44 | 45 | We can now test if the SPRIGHT function chain is able to work, using the `curl` command or apache-benchmark. Note that the port number of SPRIGHT gateway is `8080`. 46 | ```shell= 47 | # USAGE: curl http:/// 48 | 49 | curl http://10.10.1.1:8080/ 50 | ``` -------------------------------------------------------------------------------- /ebpf/sk_msg_kern.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* user accessible metadata for SK_MSG packet hook, new fields must 9 | * be added to the end of this structure 10 | */ 11 | //struct sk_msg_md { 12 | // __bpf_md_ptr(void *, data); 13 | // __bpf_md_ptr(void *, data_end); 14 | // 15 | // __u32 family; 16 | // __u32 remote_ip4; /* Stored in network byte order */ 17 | // __u32 local_ip4; /* Stored in network byte order */ 18 | // __u32 remote_ip6[4]; /* Stored in network byte order */ 19 | // __u32 local_ip6[4]; /* Stored in network byte order */ 20 | // __u32 remote_port; /* Stored in network byte order */ 21 | // __u32 local_port; /* stored in host byte order */ 22 | // __u32 size; /* Total size of sk_msg */ 23 | // 24 | // __bpf_md_ptr(struct bpf_sock *, sk); /* current socket */ 25 | //}; 26 | 27 | #define MAX_FUNC 100 // A kubernetes worker node can have up to 100 pods 28 | #define MAX_SOCK_MAP_MAP_ENTRIES 65535 29 | 30 | /* This is the data record stored in the map */ 31 | struct datarec { 32 | __u64 rx_packets; 33 | }; 34 | 35 | struct bpf_map_def SEC("maps") skmsg_stats_map = { 36 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, 37 | .key_size = sizeof(int), 38 | .value_size = sizeof(struct datarec), 39 | .max_entries = MAX_FUNC, 40 | }; 41 | 42 | struct bpf_map_def SEC("maps") sock_map = { 43 | .type = BPF_MAP_TYPE_SOCKMAP, 44 | .key_size = sizeof(int), 45 | .value_size = sizeof(int), 46 | .max_entries = MAX_SOCK_MAP_MAP_ENTRIES, 47 | .map_flags = 0 48 | }; 49 | 50 | SEC("sk_msg_tx") 51 | int bpf_skmsg_tx(struct sk_msg_md *msg) 52 | { 53 | char* data = msg->data; 54 | char* data_end = msg->data_end; 55 | bpf_printk("[sk_msg_tx] get a skmsg of length %d", msg->size); 56 | 57 | if (data + 4 > data_end) { 58 | return SK_DROP; 59 | } 60 | 61 | int next_fn_id = *((int*)data); 62 | bpf_printk("[sk_msg_tx] redirect to socket of Fn#%d", next_fn_id); 63 | 64 | struct datarec *rec = bpf_map_lookup_elem(&skmsg_stats_map, &next_fn_id); 65 | if (!rec) { 66 | bpf_printk("Fn#%d has no entry in skmsg_stats_map", next_fn_id); 67 | return SK_DROP; 68 | } 69 | 70 | rec->rx_packets++; 71 | 72 | int ret = 0; 73 | ret = bpf_msg_redirect_map(msg, &sock_map, next_fn_id, BPF_F_INGRESS); 74 | 75 | bpf_printk("TRY REDIRECT TO Fn#%d", next_fn_id); 76 | if (ret != SK_PASS) { 77 | bpf_printk("Fn#%d is not locally available, redirect to Gateway", next_fn_id); 78 | 79 | next_fn_id = 0; 80 | ret = bpf_msg_redirect_map(msg, &sock_map, next_fn_id, BPF_F_INGRESS); 81 | 82 | if (ret != SK_PASS) 83 | bpf_printk("TRY REDIRECT TO Gateway failed"); 84 | } 85 | 86 | return ret; 87 | } 88 | 89 | char _license[] SEC("license") = "GPL"; -------------------------------------------------------------------------------- /go/go.mod: -------------------------------------------------------------------------------- 1 | module nf 2 | 3 | go 1.15 4 | 5 | require github.com/sirupsen/logrus v1.8.1 // indirect 6 | -------------------------------------------------------------------------------- /go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 3 | github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= 4 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 5 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 6 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= 7 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 8 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | # Copyright 2024 University of California, Riverside 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # SPDX-License-Identifier: Apache-2.0 16 | 17 | project('spright', 'c', 18 | license: 'Apache-2.0', 19 | default_options: ['warning_level=3', 'optimization=3', 'buildtype=release'], 20 | meson_version: '>= 0.61.2' 21 | ) 22 | 23 | # Disable compiler warnings 24 | add_project_arguments('-Wno-unused-parameter', language: 'c') 25 | add_project_arguments('-Wno-error=sign-compare', language: 'c') 26 | 27 | # Check for deps 28 | libconfig_dep = dependency('libconfig', required: true) 29 | dpdk_dep = dependency('libdpdk', required: true) 30 | 31 | inc_dirs = include_directories('src/include', 'src/cstl/inc', 'src/log') 32 | 33 | # Define compiler and linker flags 34 | cflags = ['-MMD', '-MP', '-O3', '-Wall', '-Werror', '-DLOG_USE_COLOR'] 35 | ldflags = ['-L/usr/lib64'] 36 | ldlibs = ['-lbpf', '-lm', '-pthread', '-luuid'] 37 | 38 | # src files for common objects 39 | common_src = [ 40 | 'src/log/log.c', 41 | 'src/utility.c', 42 | 'src/timer.c', 43 | 'src/io_helper.c', 44 | 'src/common.c' 45 | ] 46 | 47 | common_objs = static_library('common', common_src, 48 | include_directories: inc_dirs, 49 | c_args: cflags, 50 | link_args: ldflags + ldlibs, 51 | dependencies: [libconfig_dep, dpdk_dep] 52 | ) 53 | 54 | # Include the cstl directory in root build 55 | subdir('src/cstl') 56 | 57 | # Binaries definitions 58 | # TODO: use loops to define binaries 59 | binaries = [ 60 | ['sockmap_manager', ['src/sockmap_manager.c']], 61 | ['shm_mgr_rte_ring', ['src/io_rte_ring.c', 'src/shm_mgr.c']], 62 | ['shm_mgr_sk_msg', ['src/io_sk_msg.c', 'src/shm_mgr.c']], 63 | ['gateway_rte_ring', ['src/io_rte_ring.c', 'src/gateway.c']], 64 | ['gateway_sk_msg', ['src/io_sk_msg.c', 'src/gateway.c']], 65 | ['nf_rte_ring', ['src/io_rte_ring.c', 'src/nf.c']], 66 | ['nf_sk_msg', ['src/io_sk_msg.c', 'src/nf.c']], 67 | ['nf_adservice_rte_ring', ['src/io_rte_ring.c', 'src/online_boutique/adservice.c']], 68 | ['nf_adservice_sk_msg', ['src/io_sk_msg.c', 'src/online_boutique/adservice.c']], 69 | ['nf_currencyservice_rte_ring', ['src/io_rte_ring.c', 'src/online_boutique/currencyservice.c']], 70 | ['nf_currencyservice_sk_msg', ['src/io_sk_msg.c', 'src/online_boutique/currencyservice.c']], 71 | ['nf_emailservice_rte_ring', ['src/io_rte_ring.c', 'src/online_boutique/emailservice.c']], 72 | ['nf_emailservice_sk_msg', ['src/io_sk_msg.c', 'src/online_boutique/emailservice.c']], 73 | ['nf_paymentservice_rte_ring', ['src/io_rte_ring.c', 'src/online_boutique/paymentservice.c']], 74 | ['nf_paymentservice_sk_msg', ['src/io_sk_msg.c', 'src/online_boutique/paymentservice.c']], 75 | ['nf_shippingservice_rte_ring', ['src/io_rte_ring.c', 'src/online_boutique/shippingservice.c']], 76 | ['nf_shippingservice_sk_msg', ['src/io_sk_msg.c', 'src/online_boutique/shippingservice.c']], 77 | ['nf_productcatalogservice_rte_ring', ['src/io_rte_ring.c', 'src/online_boutique/productcatalogservice.c']], 78 | ['nf_productcatalogservice_sk_msg', ['src/io_sk_msg.c', 'src/online_boutique/productcatalogservice.c']], 79 | ['nf_cartservice_rte_ring', ['src/io_rte_ring.c', 'src/online_boutique/cartservice.c']], 80 | ['nf_cartservice_sk_msg', ['src/io_sk_msg.c', 'src/online_boutique/cartservice.c']], 81 | ['nf_recommendationservice_rte_ring', ['src/io_rte_ring.c', 'src/online_boutique/recommendationservice.c']], 82 | ['nf_recommendationservice_sk_msg', ['src/io_sk_msg.c', 'src/online_boutique/recommendationservice.c']], 83 | ['nf_frontendservice_rte_ring', ['src/io_rte_ring.c', 'src/shm_rpc.c', 'src/online_boutique/frontendservice.c']], 84 | ['nf_frontendservice_sk_msg', ['src/io_sk_msg.c', 'src/shm_rpc.c', 'src/online_boutique/frontendservice.c']], 85 | ['nf_checkoutservice_rte_ring', ['src/io_rte_ring.c', 'src/online_boutique/checkoutservice.c']], 86 | ['nf_checkoutservice_sk_msg', ['src/io_sk_msg.c', 'src/online_boutique/checkoutservice.c']], 87 | ] 88 | 89 | # Generate bins 90 | foreach bin : binaries 91 | executable(bin[0], 92 | sources: bin[1] + common_src, 93 | include_directories: inc_dirs, 94 | c_args: cflags, 95 | link_args: ldflags + ldlibs, 96 | dependencies: [libconfig_dep, dpdk_dep], 97 | link_with: [common_objs, libclib_dep], 98 | install: false 99 | ) 100 | endforeach 101 | -------------------------------------------------------------------------------- /python/manifest/test-function.yaml: -------------------------------------------------------------------------------- 1 | route_id: 7 2 | spright_control_plane: 3 | sockmap_server_ip: 127.0.0.1 4 | sockmap_server_port: 8081 5 | rpc_server_ip: 127.0.0.1 6 | rpc_server_port: 8082 7 | smm_server_ip: 127.0.0.1 8 | smm_server_port: 8083 9 | function_metadata: 10 | - fn_id: 1 11 | fn_name: "Fn-1" 12 | n_threads: 32 13 | params: 14 | memory_mb: 0 15 | sleep_ms: 0 # 0.6 16 | compute: 0 17 | - fn_id: 2 18 | fn_name: "Fn-2" 19 | n_threads: 32 20 | params: 21 | memory_mb: 0 22 | sleep_ms: 0 # 2.5 23 | compute: 0 24 | - fn_id: 3 25 | fn_name: "Fn-3" 26 | n_threads: 32 27 | params: 28 | memory_mb: 0 29 | sleep_ms: 260 30 | compute: 0 31 | - fn_id: 4 32 | fn_name: "Fn-4" 33 | n_threads: 32 34 | params: 35 | memory_mb: 0 36 | sleep_ms: 0.9 37 | compute: 0 38 | - fn_id: 5 39 | fn_name: "Fn-5" 40 | n_threads: 32 41 | params: 42 | memory_mb: 0 43 | sleep_ms: 1.1 44 | compute: 0 45 | - fn_id: 6 46 | fn_name: "Fn-6" 47 | n_threads: 32 48 | params: 49 | memory_mb: 0 50 | sleep_ms: 0.5 51 | compute: 0 52 | - fn_id: 7 53 | fn_name: "Fn-7" 54 | n_threads: 32 55 | params: 56 | memory_mb: 0 57 | sleep_ms: 0.44 58 | compute: 0 59 | - fn_id: 8 60 | fn_name: "Fn-8" 61 | n_threads: 32 62 | params: 63 | memory_mb: 0 64 | sleep_ms: 0.2 65 | compute: 0 66 | - fn_id: 9 67 | fn_name: "Fn-9" 68 | n_threads: 32 69 | params: 70 | memory_mb: 0 71 | sleep_ms: 1.2 72 | compute: 0 73 | routes: 74 | - route_id: 1 75 | route_name: "Route-1" 76 | sequence: [4, 1, 9, 4, 4, 4, 4, 4, 4, 4, 4, 5] 77 | - route_id: 2 78 | route_name: "Route-2" 79 | sequence: [4, 9, 2, 1, 1, 1, 1, 1, 8, 4, 1, 4] 80 | - route_id: 3 81 | route_name: "Route-3" 82 | sequence: [1, 9] 83 | - route_id: 4 84 | route_name: "Route-4" 85 | sequence: [3, 1, 7, 8, 6, 2, 1, 1, 1, 1, 1, 4] 86 | - route_id: 5 87 | route_name: "Route-5" 88 | sequence: [1, 4, 9, 4, 2, 1, 1, 1, 1, 1, 5] 89 | - route_id: 6 90 | route_name: "Route-6" 91 | sequence: [4] 92 | - route_id: 7 93 | route_name: "Route-7" 94 | sequence: [1, 2] -------------------------------------------------------------------------------- /scripts/conda_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | wget https://repo.anaconda.com/miniconda/Miniconda3-py39_23.3.1-0-Linux-x86_64.sh 4 | chmod +x Miniconda3-py39_23.3.1-0-Linux-x86_64.sh 5 | bash Miniconda3-py39_23.3.1-0-Linux-x86_64.sh -b -p ~/miniconda3 6 | source ~/miniconda3/bin/activate 7 | conda init bash 8 | source $HOME/.bashrc 9 | 10 | rm Miniconda3-py39_23.3.1-0-Linux-x86_64.sh -------------------------------------------------------------------------------- /scripts/edit_cfg_cloudlab_hostname.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python0 2 | # Copyright 2024 University of California, Riverside 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # SPDX-License-Identifier: Apache-2.0 17 | 18 | import argparse 19 | import re 20 | import shutil 21 | import socket 22 | import sys 23 | import os 24 | 25 | def backup_file(config_path): 26 | backup_path = config_path + '.bak' 27 | shutil.copy2(config_path, backup_path) 28 | print(f"Backup created at {backup_path}") 29 | 30 | def get_hostname_suffix(): 31 | hostname = socket.gethostname() 32 | parts = hostname.split('.', 1) 33 | print(parts[1]) 34 | if len(parts) > 1: 35 | return parts[1] 36 | else: 37 | raise ValueError("Hostname does not contain a suffix part.") 38 | 39 | def update_hostnames(config_path, new_suffix): 40 | with open(config_path, 'r') as file: 41 | config = file.read() 42 | 43 | # Regular expression to find all hostnames prefixed with nodeX 44 | pattern = re.compile(r'(hostname\s*=\s*"node\d+\.)[^"]*(")', re.MULTILINE) 45 | new_config = pattern.sub(r'\1' + new_suffix + r'\2', config) 46 | 47 | with open(config_path, 'w') as file: 48 | file.write(new_config) 49 | 50 | print(f"All hostnames updated to new suffix: {new_suffix}") 51 | 52 | def main(): 53 | if sys.version_info[0] < 3: 54 | print("This script requires Python 3.") 55 | sys.exit(1) 56 | parser = argparse.ArgumentParser(description='Update hostnames suffix in config file.') 57 | parser.add_argument('config_path', type=str, help='Path to the config file') 58 | 59 | args = parser.parse_args() 60 | 61 | if not os.path.isfile(args.config_path): 62 | print(f"Error: The file '{args.config_path}' does not exist.") 63 | sys.exit(1) 64 | try: 65 | backup_file(args.config_path) 66 | new_suffix = get_hostname_suffix() 67 | update_hostnames(args.config_path, new_suffix) 68 | except Exception as e: 69 | print(f"Error: {e}") 70 | 71 | if __name__ == '__main__': 72 | main() 73 | -------------------------------------------------------------------------------- /scripts/example_nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes auto; 3 | pid /run/nginx.pid; 4 | include /etc/nginx/modules-enabled/*.conf; 5 | 6 | events { 7 | worker_connections 768; 8 | # multi_accept on; 9 | } 10 | 11 | http { 12 | 13 | ## 14 | # Basic Settings 15 | ## 16 | 17 | sendfile on; 18 | tcp_nopush on; 19 | types_hash_max_size 2048; 20 | # server_tokens off; 21 | 22 | # server_names_hash_bucket_size 64; 23 | # server_name_in_redirect off; 24 | 25 | include /etc/nginx/mime.types; 26 | default_type application/octet-stream; 27 | 28 | ## 29 | # SSL Settings 30 | ## 31 | 32 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE 33 | ssl_prefer_server_ciphers on; 34 | 35 | ## 36 | # Logging Settings 37 | ## 38 | 39 | access_log /var/log/nginx/access.log; 40 | error_log /var/log/nginx/error.log; 41 | 42 | ## 43 | # Gzip Settings 44 | ## 45 | 46 | gzip on; 47 | 48 | # gzip_vary on; 49 | # gzip_proxied any; 50 | # gzip_comp_level 6; 51 | # gzip_buffers 16 8k; 52 | # gzip_http_version 1.1; 53 | # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 54 | 55 | ## 56 | # Virtual Host Configs 57 | ## 58 | upstream backend_service { 59 | server 10.10.1.1:8080; 60 | } 61 | 62 | server { 63 | listen 80; 64 | server_name 10.10.1.3; 65 | 66 | location / { 67 | proxy_pass http://backend_service; 68 | proxy_set_header Host $host; 69 | proxy_set_header X-Real-IP $remote_addr; 70 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 71 | proxy_set_header X-Forwarded-Proto $scheme; 72 | } 73 | } 74 | 75 | include /etc/nginx/conf.d/*.conf; 76 | include /etc/nginx/sites-enabled/*; 77 | } 78 | 79 | 80 | #mail { 81 | # # See sample authentication script at: 82 | # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript 83 | # 84 | # # auth_http localhost/auth.php; 85 | # # pop3_capabilities "TOP" "USER"; 86 | # # imap_capabilities "IMAP4rev1" "UIDPLUS"; 87 | # 88 | # server { 89 | # listen localhost:110; 90 | # protocol pop3; 91 | # proxy on; 92 | # } 93 | # 94 | # server { 95 | # listen localhost:143; 96 | # protocol imap; 97 | # proxy on; 98 | # } 99 | #} 100 | -------------------------------------------------------------------------------- /scripts/microbench/pipe_latency_multithreads.c: -------------------------------------------------------------------------------- 1 | // Qi: This is a simple benchmark that measures the latency 2 | // introduced by using a Linux pipe for data transmission 3 | // $ gcc -o pipe_latency_multithreads pipe_latency_multithreads.c -lpthread 4 | // $ ./pipe_latency_multithreads 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define MIN_DATA_SIZE 8 // Minimum data size 14 | #define MAX_DATA_SIZE 8192 // Maximum data size 15 | #define NUM_ITERATIONS 20 // Number of iterations for each data size 16 | 17 | typedef struct { 18 | int data_size; 19 | int pipe_fds[2]; 20 | } thread_data_t; 21 | 22 | void error_exit(const char *message) { 23 | perror(message); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | void* writer_thread(void* arg) { 28 | thread_data_t* data = (thread_data_t*)arg; 29 | char* buffer = (char*)malloc(data->data_size); 30 | if (buffer == NULL) { 31 | error_exit("malloc failed"); 32 | } 33 | memset(buffer, 'A', data->data_size); 34 | 35 | // Write data to the pipe 36 | if (write(data->pipe_fds[1], buffer, data->data_size) == -1) { 37 | free(buffer); 38 | error_exit("write failed"); 39 | } 40 | 41 | free(buffer); 42 | return NULL; 43 | } 44 | 45 | void* reader_thread(void* arg) { 46 | thread_data_t* data = (thread_data_t*)arg; 47 | char* buffer = (char*)malloc(data->data_size); 48 | if (buffer == NULL) { 49 | error_exit("malloc failed"); 50 | } 51 | 52 | // Read data from the pipe 53 | if (read(data->pipe_fds[0], buffer, data->data_size) == -1) { 54 | free(buffer); 55 | error_exit("read failed"); 56 | } 57 | 58 | free(buffer); 59 | return NULL; 60 | } 61 | 62 | long measure_latency(int data_size) { 63 | pthread_t writer, reader; 64 | thread_data_t thread_data; 65 | struct timeval start_time, end_time; 66 | long latency; 67 | 68 | // Initialize pipe and thread data 69 | thread_data.data_size = data_size; 70 | if (pipe(thread_data.pipe_fds) == -1) { 71 | error_exit("pipe failed"); 72 | } 73 | 74 | // Get the start time 75 | if (gettimeofday(&start_time, NULL) == -1) { 76 | error_exit("gettimeofday failed"); 77 | } 78 | 79 | // Create writer and reader threads 80 | if (pthread_create(&writer, NULL, writer_thread, &thread_data) != 0) { 81 | error_exit("pthread_create writer failed"); 82 | } 83 | if (pthread_create(&reader, NULL, reader_thread, &thread_data) != 0) { 84 | error_exit("pthread_create reader failed"); 85 | } 86 | 87 | // Wait for both threads to complete 88 | pthread_join(writer, NULL); 89 | pthread_join(reader, NULL); 90 | 91 | // Get the end time 92 | if (gettimeofday(&end_time, NULL) == -1) { 93 | error_exit("gettimeofday failed"); 94 | } 95 | 96 | // Calculate the latency in microseconds 97 | latency = (end_time.tv_sec - start_time.tv_sec) * 1000000L + 98 | (end_time.tv_usec - start_time.tv_usec); 99 | 100 | // Close the pipe 101 | close(thread_data.pipe_fds[0]); 102 | close(thread_data.pipe_fds[1]); 103 | 104 | return latency; 105 | } 106 | 107 | int main() { 108 | int data_size; 109 | long total_latency, average_latency; 110 | 111 | printf("Data Size (bytes)\tAverage Latency (microseconds)\n"); 112 | 113 | for (data_size = MIN_DATA_SIZE; data_size <= MAX_DATA_SIZE; data_size *= 2) { 114 | total_latency = 0; 115 | 116 | for (int i = 0; i < NUM_ITERATIONS; i++) { 117 | total_latency += measure_latency(data_size); 118 | } 119 | 120 | average_latency = total_latency / NUM_ITERATIONS; 121 | 122 | printf("%d\t\t\t%ld\n", data_size, average_latency); 123 | } 124 | 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /scripts/microbench/pipe_latency_singlethread.c: -------------------------------------------------------------------------------- 1 | // Qi: This is a simple benchmark that measures the latency 2 | // introduced by using a Linux pipe for data transmission 3 | // $ gcc -o pipe_latency_singlethread pipe_latency_singlethread.c 4 | // $ ./pipe_latency_singlethread 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define MIN_DATA_SIZE 8 // Minimum data size 13 | #define MAX_DATA_SIZE 8192 // Maximum data size 14 | #define NUM_ITERATIONS 20 // Number of iterations for each data size 15 | 16 | void error_exit(const char *message) { 17 | perror(message); 18 | exit(EXIT_FAILURE); 19 | } 20 | 21 | long measure_latency(int data_size) { 22 | int pipe_fds[2]; 23 | char *data = (char *)malloc(data_size); 24 | struct timeval start_time, end_time; 25 | long latency; 26 | 27 | if (data == NULL) { 28 | error_exit("malloc failed"); 29 | } 30 | 31 | memset(data, 'A', data_size); 32 | 33 | if (pipe(pipe_fds) == -1) { 34 | free(data); 35 | error_exit("pipe failed"); 36 | } 37 | 38 | if (gettimeofday(&start_time, NULL) == -1) { 39 | free(data); 40 | error_exit("gettimeofday failed"); 41 | } 42 | 43 | if (write(pipe_fds[1], data, data_size) == -1) { 44 | free(data); 45 | error_exit("write failed"); 46 | } 47 | 48 | if (read(pipe_fds[0], data, data_size) == -1) { 49 | free(data); 50 | error_exit("read failed"); 51 | } 52 | 53 | if (gettimeofday(&end_time, NULL) == -1) { 54 | free(data); 55 | error_exit("gettimeofday failed"); 56 | } 57 | 58 | latency = (end_time.tv_sec - start_time.tv_sec) * 1000000L + 59 | (end_time.tv_usec - start_time.tv_usec); 60 | 61 | free(data); 62 | close(pipe_fds[0]); 63 | close(pipe_fds[1]); 64 | 65 | return latency; 66 | } 67 | 68 | int main() { 69 | int data_size; 70 | long total_latency, average_latency; 71 | 72 | printf("Data Size (bytes)\tAverage Latency (microseconds)\n"); 73 | 74 | for (data_size = MIN_DATA_SIZE; data_size <= MAX_DATA_SIZE; data_size *= 2) { 75 | total_latency = 0; 76 | 77 | for (int i = 0; i < NUM_ITERATIONS; i++) { 78 | total_latency += measure_latency(data_size); 79 | } 80 | 81 | average_latency = total_latency / NUM_ITERATIONS; 82 | 83 | printf("%d\t\t\t%ld\n", data_size, average_latency); 84 | } 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /scripts/run_once_single_node_dummy_with_nginx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # README: several points you may pay attention to 4 | # (1) If you use apache benchmark, remember to add a "/" at the end of the url 5 | # Otherwise, apache benchmark cannot identify the url 6 | # (2) Depending on the kernel version, apache benchmark may not scale up to 7 | # multiple cores; you may need to run multiple apache benchmarks in parallel 8 | # to generate sufficient load 9 | # (3) You need to install the SPRIGHT/Palladium deps in advance; This script 10 | # doesn't install the deps for you; You also need to configure the NGINX ingress 11 | # or Palladium ingress in advance 12 | # (4) Make sure you can launch the load test manually, this script will then be 13 | # tremendously helpful 14 | 15 | if [ $# -ne 3 ]; then 16 | echo "This script is to automate Palladium Ingress experiment." 17 | echo "Running this script on your local machine." 18 | echo "Make sure you have ssh access configured." 19 | echo "usage: $0