Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(proxy-wasm) foreign function support #626

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

casimiro
Copy link
Contributor

@casimiro casimiro commented Nov 18, 2024

Foreign Function Support

The Proxy-Wasm spec defines the function proxy_call_foreign_function and the callback proxy_on_foreign_function that filter developers can use to invoke host specific functions, a.k.a. foreign functions, and receive callbacks.

A foreign function invoked with proxy_call_foreign_function may return its value immediately -- as part of the returned value of the proxy_call_foreign_function call; or it can return it later, writing it to the FOREIGN_FUNCTION_ARGUMENTS buffer, and invoking proxy_on_foreign_function with an id identifying the function initially called.

This PR adds support for the mechanism described above; and although the spec doesn't restrict when foreign functions can be called, in ngx_wasm_module they cannot be invoked from proxy_on_configure or proxy_on_vm_start.

DNS resolution

This PR also exposes the Lua DNS resolver through the resolve_lua foreign function.

This function expects the name to be resolved as its single argument. If the name can be resolved without performing any IO, the resolved address is put in the returned value of proxy_call_foreign_function.

If the resolver needs to forward the resolution request to a DNS server, the resolved address and the name itself are written to the FOREIGN_FUNCTION_ARGUMENTS buffer and the proxy_on_foreign_function callback is invoked with function_id 0, as soon as the address is returned from the server.

TODO

  • on_tick support
  • general review
  • update docs

@casimiro casimiro added the pr/work-in-progress PR: Work in progress label Nov 18, 2024
@casimiro casimiro force-pushed the feat/wasm-foreign-function branch 5 times, most recently from d4b4267 to 99b8e75 Compare November 19, 2024 21:58
Copy link

codecov bot commented Nov 19, 2024

Codecov Report

Attention: Patch coverage is 71.42857% with 66 lines in your changes missing coverage. Please review.

Project coverage is 90.45578%. Comparing base (9238d4a) to head (2ecb389).

Files with missing lines Patch % Lines
src/common/proxy_wasm/ngx_proxy_wasm_host.c 65.00000% 42 Missing ⚠️
src/common/proxy_wasm/ngx_proxy_wasm.c 54.54545% 10 Missing ⚠️
...ommon/proxy_wasm/ngx_proxy_wasm_foreign_callback.c 85.18519% 8 Missing ⚠️
src/http/ngx_http_wasm_util.c 80.00000% 3 Missing ⚠️
src/http/proxy_wasm/ngx_http_proxy_wasm.c 88.23529% 2 Missing ⚠️
src/http/proxy_wasm/ngx_http_proxy_wasm_dispatch.c 50.00000% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                 Coverage Diff                 @@
##                main        #626         +/-   ##
===================================================
- Coverage   90.84180%   90.45578%   -0.38603%     
===================================================
  Files             52          53          +1     
  Lines          11214       11431        +217     
===================================================
+ Hits           10187       10340        +153     
- Misses          1027        1091         +64     
Files with missing lines Coverage Δ
src/common/proxy_wasm/ngx_proxy_wasm.h 92.30769% <ø> (ø)
src/common/proxy_wasm/ngx_proxy_wasm_util.c 94.25287% <100.00000%> (ø)
src/http/proxy_wasm/ngx_http_proxy_wasm_dispatch.c 91.95980% <50.00000%> (+0.27276%) ⬆️
src/http/proxy_wasm/ngx_http_proxy_wasm.c 93.30144% <88.23529%> (-0.44857%) ⬇️
src/http/ngx_http_wasm_util.c 86.95652% <80.00000%> (-0.27752%) ⬇️
...ommon/proxy_wasm/ngx_proxy_wasm_foreign_callback.c 85.18519% <85.18519%> (ø)
src/common/proxy_wasm/ngx_proxy_wasm.c 91.78228% <54.54545%> (-0.89532%) ⬇️
src/common/proxy_wasm/ngx_proxy_wasm_host.c 90.46673% <65.00000%> (-3.44533%) ⬇️

... and 1 file with indirect coverage changes

Flag Coverage Δ
unit 90.40686% <81.00000%> (-0.17338%) ⬇️
valgrind 80.93180% <10.59908%> (-1.57678%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

---- 🚨 Try these New Features:

@casimiro casimiro changed the title feat(proxy-wasm) foreign function feat(proxy-wasm) foreign function support Nov 20, 2024
@casimiro casimiro force-pushed the feat/wasm-foreign-function branch 4 times, most recently from 7aa55fb to 08ec198 Compare November 21, 2024 13:11
#ifdef NGX_WASM_HTTP
ngx_http_proxy_wasm_dispatch_t *call; /* swap pointer for host functions */
ngx_http_proxy_wasm_dispatch_t *call; /* swap pointer for host functions */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dispatch_call

#endif
ngx_queue_t calls;
ngx_queue_t calls;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dispatch_calls

#endif
ngx_queue_t calls;
ngx_queue_t calls;
ngx_proxy_wasm_foreign_cb_t *fcallback;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

foreign_call

ngx_queue_t calls;
ngx_queue_t calls;
ngx_proxy_wasm_foreign_cb_t *fcallback;
ngx_queue_t fcallbacks;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

foreign_calls

@@ -415,6 +424,9 @@ ngx_proxy_wasm_err_e ngx_proxy_wasm_run_step(ngx_proxy_wasm_exec_t *pwexec,
ngx_proxy_wasm_step_e step);
ngx_uint_t ngx_proxy_wasm_dispatch_calls_total(ngx_proxy_wasm_exec_t *pwexec);
void ngx_proxy_wasm_dispatch_calls_cancel(ngx_proxy_wasm_exec_t *pwexec);
ngx_uint_t ngx_proxy_wasm_foreign_callbacks_total(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

foreign_calls_total
...

void
ngx_proxy_wasm_foreign_callback_destroy(ngx_proxy_wasm_foreign_cb_t *cb)
{

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

ngx_wa_assert(pwexec);
ngx_wa_assert(size);

cl = ngx_alloc_chain_link(pwexec->pool);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ngx_wasm_chain_get_free_buf

return NGX_ERROR;
}

/* TODO: if size exceeds a threshold, split allocation into N buffers */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ngx_wa_assert(len < NGX_MAX_ERRLEN)

}


ngx_int_t
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void

ret_size = NGX_WAVM_HOST_LIFT(instance, args[5].of.i32, int32_t);

if (ngx_str_eq(fname.data, fname.len, "resolve_lua", -1)) {
return ngx_proxy_wasm_hfuncs_resolve_lua(instance, rctx, &fargs,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ngx_proxy_wasm_foreign_call_lua_resolve (?) -> foreign_call.c


pwexec = ngx_proxy_wasm_instance2pwexec(instance);

cb = ngx_proxy_wasm_foreign_callback_alloc(pwexec);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(inlined)

b = cb->args_out->buf;
s = *b->start; /* first byte is the length of the resolved address */

p = ngx_proxy_wasm_alloc(pwexec, s);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

catch bad alloc



ngx_int_t
ngx_http_wasm_create_fake_req_ctx(ngx_proxy_wasm_exec_t *pwexec,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create_fake_rctx

ngx_queue_t q;
ngx_proxy_wasm_exec_t *pwexec;
#if (NGX_WASM_HTTP)
ngx_http_wasm_req_ctx_t *rctx;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ngx_http_wasm_req_ctx_t *rctx;


break;
#endif

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change


*(p++) = sizeof(struct in6_addr);
p = ngx_cpymem(p, &sin6->sin6_addr, sizeof(struct in6_addr));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

p++;
goto not_found;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ngx_wa_assert(rslv_ctx->naddrs == 1) (perhaps?)

ngx_wasm_socket_tcp_t *sock;
ngx_proxy_wasm_exec_t *pwexec;
ngx_proxy_wasm_foreign_cb_t *cb;
ngx_wavm_ptr_t p = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ngx_wavm_ptr_t p = 0;
ngx_wavm_ptr_t p;

cb->rctx = rctx;
}

sock = ngx_palloc(pwexec->pool, sizeof(ngx_wasm_socket_tcp_t));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sock = ngx_palloc(pwexec->pool, sizeof(ngx_wasm_socket_tcp_t));
sock = ngx_pcalloc(pwexec->pool, sizeof(ngx_wasm_socket_tcp_t));

{
ngx_proxy_wasm_foreign_cb_t *cb;

cb = ngx_palloc(pwexec->pool, sizeof(ngx_proxy_wasm_foreign_cb_t));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cb = ngx_palloc(pwexec->pool, sizeof(ngx_proxy_wasm_foreign_cb_t));
cb = ngx_pcalloc(pwexec->pool, sizeof(ngx_proxy_wasm_foreign_cb_t));
  • inlined

goto error;
}

cb->fcode = NGX_PROXY_WASM_FOREIGN_RESOLVE;
Copy link
Member

@thibaultcha thibaultcha Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try with a function pointer when all those routiens move to "foreign_call.c"

b->last = ngx_cpymem(b->last, data->data, data->len);
}

/* TODO: data->len > b_size */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move up to the assert

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr/work-in-progress PR: Work in progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants