This is an automated email from the ASF dual-hosted git repository.
kichan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new ab0a572882 Remove reference to WAVM (#10147)
ab0a572882 is described below
commit ab0a572882377165109fecc6f818154bdacb4bca
Author: Kit Chan <[email protected]>
AuthorDate: Fri Aug 4 09:47:50 2023 -0700
Remove reference to WAVM (#10147)
---
configure.ac | 3 -
doc/admin-guide/plugins/wasm.en.rst | 15 +--
plugins/experimental/wasm/Makefile.inc | 2 +
.../wasm/lib/include/proxy-wasm/context.h | 6 +-
.../wasm/lib/include/proxy-wasm/wasm.h | 1 +
plugins/experimental/wasm/lib/src/context.cc | 6 ++
plugins/experimental/wasm/lib/src/hash.cc | 54 ++++++++++
plugins/experimental/wasm/lib/src/hash.h | 27 +++++
plugins/experimental/wasm/lib/src/wamr/wamr.cc | 28 +++--
plugins/experimental/wasm/lib/src/wasm.cc | 116 +++++++++++++++------
10 files changed, 201 insertions(+), 57 deletions(-)
diff --git a/configure.ac b/configure.ac
index 73d8a2c587..91445116c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1441,9 +1441,6 @@ AC_SUBST(use_quic)
AC_SUBST(has_quiche)
AM_CONDITIONAL([ENABLE_QUIC], [test "x$enable_quic" = "xyes"])
-# Check for optional WAVM library
-TS_CHECK_WAVM
-
#
# Enable experimental/uri_signing plugin
# This is here, instead of above, because it needs to know if PCRE is
available.
diff --git a/doc/admin-guide/plugins/wasm.en.rst
b/doc/admin-guide/plugins/wasm.en.rst
index cf92af6157..ad07543c5a 100644
--- a/doc/admin-guide/plugins/wasm.en.rst
+++ b/doc/admin-guide/plugins/wasm.en.rst
@@ -36,7 +36,7 @@ How it Works
The plugin uses the library and header files from the Proxy-Wasm project.
-*
https://github.com/proxy-wasm/proxy-wasm-cpp-host/tree/72ce32f7b11f9190edf874028255e1309e41690f
+*
https://github.com/proxy-wasm/proxy-wasm-cpp-host/tree/b7e690703c7f26707438a2f1ebd7c197bc8f0296
*
https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/tree/fd0be8405db25de0264bdb78fae3a82668c03782
Proxy-Wasm in turn uses an underlying WebAssembly runtime to execute the
WebAssembly module. (Currently only WAMR and
@@ -56,9 +56,9 @@ Compiling the Plugin
::
- wget
https://github.com/bytecodealliance/wasm-micro-runtime/archive/c3d66f916ef8093e5c8cacf3329ed968f807cf58.tar.gz
- tar zxvf c3d66f916ef8093e5c8cacf3329ed968f807cf58.tar.gz
- cd wasm-micro-runtime-c3d66f916ef8093e5c8cacf3329ed968f807cf58
+ wget
https://github.com/bytecodealliance/wasm-micro-runtime/archive/refs/tags/WAMR-1.2.1.tar.gz
+ tar zxvf WAMR-1.2.1.tar.gz
+ cd wasm-micro-runtime-WAMR-1.2.1
cp core/iwasm/include/* /usr/local/include/
cd product-mini/platforms/linux
mkdir build
@@ -71,13 +71,14 @@ Compiling the Plugin
::
- wget
https://github.com/WasmEdge/WasmEdge/archive/refs/tags/proxy-wasm/0.11.2.tar.gz
- tar zxvf 0.11.2.tar.gz
- cd WasmEdge-proxy-wasm-0.11.2/utils
+ wget
https://github.com/WasmEdge/WasmEdge/archive/refs/tags/proxy-wasm/0.13.1.tar.gz
+ tar zxvf 0.13.1.tar.gz
+ cd WasmEdge-proxy-wasm-0.13.1/utils
./install.sh
* Copy contents from ~/.wasmedge/include to /usr/local/include
* Copy contents from ~/.wasmedge/lib to /usr/local/lib
+* The installation script will make changes to your environment variables. You
can comment those out for now before compiling the plugin.
**Configure ATS to compile with experimental plugins**
diff --git a/plugins/experimental/wasm/Makefile.inc
b/plugins/experimental/wasm/Makefile.inc
index ebd92050c5..340df03896 100755
--- a/plugins/experimental/wasm/Makefile.inc
+++ b/plugins/experimental/wasm/Makefile.inc
@@ -55,6 +55,8 @@ experimental_wasm_wasm_la_SOURCES = \
experimental/wasm/lib/include/proxy-wasm/shared_data.h \
experimental/wasm/lib/src/shared_queue.cc \
experimental/wasm/lib/include/proxy-wasm/shared_queue.h \
+ experimental/wasm/lib/src/hash.cc \
+ experimental/wasm/lib/src/hash.h \
experimental/wasm/lib/src/signature_util.cc \
experimental/wasm/lib/include/proxy-wasm/signature_util.h \
experimental/wasm/lib/src/vm_id_handle.cc \
diff --git a/plugins/experimental/wasm/lib/include/proxy-wasm/context.h
b/plugins/experimental/wasm/lib/include/proxy-wasm/context.h
index 652b86b6e0..ab99cad70a 100644
--- a/plugins/experimental/wasm/lib/include/proxy-wasm/context.h
+++ b/plugins/experimental/wasm/lib/include/proxy-wasm/context.h
@@ -23,6 +23,7 @@
#include <map>
#include <memory>
#include <string>
+#include <string_view>
#include <vector>
#include "include/proxy-wasm/context_interface.h"
@@ -53,8 +54,7 @@ struct PluginBase {
std::string_view key)
: name_(std::string(name)), root_id_(std::string(root_id)),
vm_id_(std::string(vm_id)),
engine_(std::string(engine)),
plugin_configuration_(plugin_configuration),
- fail_open_(fail_open),
- key_(root_id_ + "||" + plugin_configuration_ + "||" +
std::string(key)),
+ fail_open_(fail_open), key_(makePluginKey(root_id,
plugin_configuration, key)),
log_prefix_(makeLogPrefix()) {}
const std::string name_;
@@ -69,6 +69,8 @@ struct PluginBase {
private:
std::string makeLogPrefix() const;
+ static std::string makePluginKey(std::string_view root_id, std::string_view
plugin_configuration,
+ std::string_view key);
const std::string key_;
const std::string log_prefix_;
diff --git a/plugins/experimental/wasm/lib/include/proxy-wasm/wasm.h
b/plugins/experimental/wasm/lib/include/proxy-wasm/wasm.h
index 23ed3c1da6..1a785a8f9a 100644
--- a/plugins/experimental/wasm/lib/include/proxy-wasm/wasm.h
+++ b/plugins/experimental/wasm/lib/include/proxy-wasm/wasm.h
@@ -337,6 +337,7 @@ public:
protected:
std::shared_ptr<WasmBase> wasm_base_;
+ std::unordered_map<std::string, bool> plugin_canary_cache_;
};
std::string makeVmKey(std::string_view vm_id, std::string_view configuration,
diff --git a/plugins/experimental/wasm/lib/src/context.cc
b/plugins/experimental/wasm/lib/src/context.cc
index 29037ae438..5353a52a54 100644
--- a/plugins/experimental/wasm/lib/src/context.cc
+++ b/plugins/experimental/wasm/lib/src/context.cc
@@ -22,6 +22,7 @@
#include "include/proxy-wasm/context.h"
#include "include/proxy-wasm/wasm.h"
+#include "src/hash.h"
#include "src/shared_data.h"
#include "src/shared_queue.h"
@@ -85,6 +86,11 @@ std::string PluginBase::makeLogPrefix() const {
return prefix;
}
+std::string PluginBase::makePluginKey(std::string_view root_id,
+ std::string_view plugin_configuration,
std::string_view key) {
+ return Sha256String({root_id, "||", plugin_configuration, "||", key});
+}
+
ContextBase::ContextBase() : parent_context_(this) {}
ContextBase::ContextBase(WasmBase *wasm) : wasm_(wasm), parent_context_(this) {
diff --git a/plugins/experimental/wasm/lib/src/hash.cc
b/plugins/experimental/wasm/lib/src/hash.cc
new file mode 100644
index 0000000000..f2d1ded138
--- /dev/null
+++ b/plugins/experimental/wasm/lib/src/hash.cc
@@ -0,0 +1,54 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/hash.h"
+
+#include <string>
+#include <vector>
+
+#include <openssl/sha.h>
+
+namespace proxy_wasm {
+
+namespace {
+
+std::string BytesToHex(const std::vector<uint8_t> &bytes) {
+ static const char *const hex = "0123456789ABCDEF";
+ std::string result;
+ result.reserve(bytes.size() * 2);
+ for (auto byte : bytes) {
+ result.push_back(hex[byte >> 4]);
+ result.push_back(hex[byte & 0xf]);
+ }
+ return result;
+}
+
+} // namespace
+
+std::vector<uint8_t> Sha256(const std::vector<std::string_view> &parts) {
+ uint8_t sha256[SHA256_DIGEST_LENGTH];
+ SHA256_CTX sha_ctx;
+ SHA256_Init(&sha_ctx);
+ for (auto part : parts) {
+ SHA256_Update(&sha_ctx, part.data(), part.size());
+ }
+ SHA256_Final(sha256, &sha_ctx);
+ return std::vector<uint8_t>(std::begin(sha256), std::end(sha256));
+}
+
+std::string Sha256String(const std::vector<std::string_view> &parts) {
+ return BytesToHex(Sha256(parts));
+}
+
+} // namespace proxy_wasm
\ No newline at end of file
diff --git a/plugins/experimental/wasm/lib/src/hash.h
b/plugins/experimental/wasm/lib/src/hash.h
new file mode 100644
index 0000000000..40d03e9d4c
--- /dev/null
+++ b/plugins/experimental/wasm/lib/src/hash.h
@@ -0,0 +1,27 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <openssl/sha.h>
+
+namespace proxy_wasm {
+
+std::vector<uint8_t> Sha256(const std::vector<std::string_view> &parts);
+std::string Sha256String(const std::vector<std::string_view> &parts);
+
+} // namespace proxy_wasm
diff --git a/plugins/experimental/wasm/lib/src/wamr/wamr.cc
b/plugins/experimental/wasm/lib/src/wamr/wamr.cc
index 577b6784f3..ea3d140e7d 100644
--- a/plugins/experimental/wasm/lib/src/wamr/wamr.cc
+++ b/plugins/experimental/wasm/lib/src/wamr/wamr.cc
@@ -125,10 +125,12 @@ bool Wamr::load(std::string_view bytecode,
std::string_view /*precompiled*/,
return false;
}
- WasmByteVec vec;
- wasm_byte_vec_new(vec.get(), bytecode.size(), bytecode.data());
-
- module_ = wasm_module_new(store_.get(), vec.get());
+ wasm_byte_vec_t binary = {.size = bytecode.size(),
+ .data = (char *)bytecode.data(),
+ .num_elems = bytecode.size(),
+ .size_of_elem = sizeof(byte_t),
+ .lock = nullptr};
+ module_ = wasm_module_new(store_.get(), &binary);
if (module_ == nullptr) {
return false;
}
@@ -259,9 +261,15 @@ bool Wamr::link(std::string_view /*debug_name*/) {
const wasm_name_t *name_ptr =
wasm_importtype_name(import_types.get()->data[i]);
const wasm_externtype_t *extern_type =
wasm_importtype_type(import_types.get()->data[i]);
- std::string_view module_name(module_name_ptr->data, module_name_ptr->size);
- std::string_view name(name_ptr->data, name_ptr->size);
- assert(name_ptr->size > 0);
+ if (std::strlen(name_ptr->data) == 0) {
+ fail(FailState::UnableToInitializeCode, std::string("The name field of
import_types[") +
+ std::to_string(i) +
std::string("] is empty"));
+ return false;
+ }
+
+ std::string_view module_name(module_name_ptr->data);
+ std::string_view name(name_ptr->data);
+
switch (wasm_externtype_kind(extern_type)) {
case WASM_EXTERN_FUNC: {
auto it = host_functions_.find(std::string(module_name) + "." +
std::string(name));
@@ -344,17 +352,15 @@ bool Wamr::link(std::string_view /*debug_name*/) {
wasm_instance_exports(instance_.get(), exports.get());
for (size_t i = 0; i < export_types.get()->size; i++) {
- const wasm_externtype_t *exp_extern_type =
wasm_exporttype_type(export_types.get()->data[i]);
wasm_extern_t *actual_extern = exports.get()->data[i];
wasm_externkind_t kind = wasm_extern_kind(actual_extern);
- assert(kind == wasm_externtype_kind(exp_extern_type));
+ assert(kind ==
wasm_externtype_kind(wasm_exporttype_type(export_types.get()->data[i])));
switch (kind) {
case WASM_EXTERN_FUNC: {
WasmFuncPtr func = wasm_func_copy(wasm_extern_as_func(actual_extern));
const wasm_name_t *name_ptr =
wasm_exporttype_name(export_types.get()->data[i]);
- module_functions_.insert_or_assign(std::string(name_ptr->data,
name_ptr->size),
- std::move(func));
+ module_functions_.insert_or_assign(std::string(name_ptr->data),
std::move(func));
} break;
case WASM_EXTERN_GLOBAL: {
// TODO(mathetake): add support when/if needed.
diff --git a/plugins/experimental/wasm/lib/src/wasm.cc
b/plugins/experimental/wasm/lib/src/wasm.cc
index 5519b3e774..cb1dd9b3ac 100644
--- a/plugins/experimental/wasm/lib/src/wasm.cc
+++ b/plugins/experimental/wasm/lib/src/wasm.cc
@@ -23,54 +23,75 @@
#include <limits>
#include <memory>
#include <mutex>
+#include <queue>
#include <string>
#include <unordered_map>
#include <utility>
-#include <openssl/sha.h>
-
#include "include/proxy-wasm/bytecode_util.h"
#include "include/proxy-wasm/signature_util.h"
#include "include/proxy-wasm/vm_id_handle.h"
+#include "src/hash.h"
namespace proxy_wasm {
namespace {
-// Map from Wasm Key to the local Wasm instance.
+// Map from Wasm key to the thread-local Wasm instance.
thread_local std::unordered_map<std::string, std::weak_ptr<WasmHandleBase>>
local_wasms;
+// Wasm key queue to track stale entries in `local_wasms`.
+thread_local std::queue<std::string> local_wasms_keys;
+
+// Map from plugin key to the thread-local plugin instance.
thread_local std::unordered_map<std::string, std::weak_ptr<PluginHandleBase>>
local_plugins;
+// Plugin key queue to track stale entries in `local_plugins`.
+thread_local std::queue<std::string> local_plugins_keys;
+
+// Check no more than `MAX_LOCAL_CACHE_GC_CHUNK_SIZE` cache entries at a time
during stale entries
+// cleanup.
+const size_t MAX_LOCAL_CACHE_GC_CHUNK_SIZE = 64;
+
// Map from Wasm Key to the base Wasm instance, using a pointer to avoid the
initialization fiasco.
std::mutex base_wasms_mutex;
std::unordered_map<std::string, std::weak_ptr<WasmHandleBase>> *base_wasms =
nullptr;
-std::vector<uint8_t> Sha256(const std::vector<std::string_view> &parts) {
- uint8_t sha256[SHA256_DIGEST_LENGTH];
- SHA256_CTX sha_ctx;
- SHA256_Init(&sha_ctx);
- for (auto part : parts) {
- SHA256_Update(&sha_ctx, part.data(), part.size());
- }
- SHA256_Final(sha256, &sha_ctx);
- return std::vector<uint8_t>(std::begin(sha256), std::end(sha256));
+void cacheLocalWasm(const std::string &key, const
std::shared_ptr<WasmHandleBase> &wasm_handle) {
+ local_wasms[key] = wasm_handle;
+ local_wasms_keys.emplace(key);
+}
+
+void cacheLocalPlugin(const std::string &key,
+ const std::shared_ptr<PluginHandleBase> &plugin_handle) {
+ local_plugins[key] = plugin_handle;
+ local_plugins_keys.emplace(key);
}
-std::string BytesToHex(const std::vector<uint8_t> &bytes) {
- static const char *const hex = "0123456789ABCDEF";
- std::string result;
- result.reserve(bytes.size() * 2);
- for (auto byte : bytes) {
- result.push_back(hex[byte >> 4]);
- result.push_back(hex[byte & 0xf]);
+template <class T>
+void removeStaleLocalCacheEntries(std::unordered_map<std::string,
std::weak_ptr<T>> &cache,
+ std::queue<std::string> &keys) {
+ auto num_keys_to_check = std::min(MAX_LOCAL_CACHE_GC_CHUNK_SIZE,
keys.size());
+ for (size_t i = 0; i < num_keys_to_check; i++) {
+ std::string key(keys.front());
+ keys.pop();
+
+ const auto it = cache.find(key);
+ if (it == cache.end()) {
+ continue;
+ }
+
+ if (it->second.expired()) {
+ cache.erase(it);
+ } else {
+ keys.push(std::move(key));
+ }
}
- return result;
}
} // namespace
std::string makeVmKey(std::string_view vm_id, std::string_view
vm_configuration,
std::string_view code) {
- return BytesToHex(Sha256({vm_id, vm_configuration, code}));
+ return Sha256String({vm_id, "||", vm_configuration, "||", code});
}
class WasmBase::ShutdownHandle {
@@ -472,6 +493,10 @@ bool WasmHandleBase::canary(const
std::shared_ptr<PluginBase> &plugin,
if (this->wasm() == nullptr) {
return false;
}
+ auto it = plugin_canary_cache_.find(plugin->key());
+ if (it != plugin_canary_cache_.end()) {
+ return it->second;
+ }
auto configuration_canary_handle = clone_factory(shared_from_this());
if (!configuration_canary_handle) {
this->wasm()->fail(FailState::UnableToCloneVm, "Failed to clone Base
Wasm");
@@ -490,9 +515,11 @@ bool WasmHandleBase::canary(const
std::shared_ptr<PluginBase> &plugin,
if (!configuration_canary_handle->wasm()->configure(root_context, plugin)) {
configuration_canary_handle->wasm()->fail(FailState::ConfigureFailed,
"Failed to configure base Wasm
plugin");
+ plugin_canary_cache_[plugin->key()] = false;
return false;
}
configuration_canary_handle->kill();
+ plugin_canary_cache_[plugin->key()] = true;
return true;
}
@@ -542,14 +569,15 @@ std::shared_ptr<WasmHandleBase> createWasm(const
std::string &vm_key, const std:
std::shared_ptr<WasmHandleBase> getThreadLocalWasm(std::string_view vm_key) {
auto it = local_wasms.find(std::string(vm_key));
- if (it == local_wasms.end()) {
- return nullptr;
- }
- auto wasm = it->second.lock();
- if (!wasm) {
- local_wasms.erase(std::string(vm_key));
+ if (it != local_wasms.end()) {
+ auto wasm = it->second.lock();
+ if (wasm) {
+ return wasm;
+ }
+ local_wasms.erase(it);
}
- return wasm;
+ removeStaleLocalCacheEntries(local_wasms, local_wasms_keys);
+ return nullptr;
}
static std::shared_ptr<WasmHandleBase>
@@ -563,9 +591,9 @@ getOrCreateThreadLocalWasm(const
std::shared_ptr<WasmHandleBase> &base_handle,
if (wasm_handle) {
return wasm_handle;
}
- // Remove stale entry.
- local_wasms.erase(vm_key);
+ local_wasms.erase(it);
}
+ removeStaleLocalCacheEntries(local_wasms, local_wasms_keys);
// Create and initialize new thread-local WasmVM.
auto wasm_handle = clone_factory(base_handle);
if (!wasm_handle) {
@@ -577,7 +605,7 @@ getOrCreateThreadLocalWasm(const
std::shared_ptr<WasmHandleBase> &base_handle,
base_handle->wasm()->fail(FailState::UnableToInitializeCode, "Failed to
initialize Wasm code");
return nullptr;
}
- local_wasms[vm_key] = wasm_handle;
+ cacheLocalWasm(vm_key, wasm_handle);
wasm_handle->wasm()->wasm_vm()->addFailCallback([vm_key](proxy_wasm::FailState
fail_state) {
if (fail_state == proxy_wasm::FailState::RuntimeError) {
// If VM failed, erase the entry so that:
@@ -600,9 +628,9 @@ std::shared_ptr<PluginHandleBase>
getOrCreateThreadLocalPlugin(
if (plugin_handle) {
return plugin_handle;
}
- // Remove stale entry.
- local_plugins.erase(key);
+ local_plugins.erase(it);
}
+ removeStaleLocalCacheEntries(local_plugins, local_plugins_keys);
// Get thread-local WasmVM.
auto wasm_handle = getOrCreateThreadLocalWasm(base_handle, clone_factory);
if (!wasm_handle) {
@@ -620,7 +648,7 @@ std::shared_ptr<PluginHandleBase>
getOrCreateThreadLocalPlugin(
return nullptr;
}
auto plugin_handle = plugin_factory(wasm_handle, plugin);
- local_plugins[key] = plugin_handle;
+ cacheLocalPlugin(key, plugin_handle);
wasm_handle->wasm()->wasm_vm()->addFailCallback([key](proxy_wasm::FailState
fail_state) {
if (fail_state == proxy_wasm::FailState::RuntimeError) {
// If VM failed, erase the entry so that:
@@ -642,4 +670,24 @@ void clearWasmCachesForTesting() {
}
}
+std::vector<std::string> staleLocalPluginsKeysForTesting() {
+ std::vector<std::string> keys;
+ for (const auto &kv : local_plugins) {
+ if (kv.second.expired()) {
+ keys.push_back(kv.first);
+ }
+ }
+ return keys;
+}
+
+std::vector<std::string> staleLocalWasmsKeysForTesting() {
+ std::vector<std::string> keys;
+ for (const auto &kv : local_wasms) {
+ if (kv.second.expired()) {
+ keys.push_back(kv.first);
+ }
+ }
+ return keys;
+}
+
} // namespace proxy_wasm