') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - phoenix-dataplane/phoenix: Phoenix dataplane system service · GitHub
Skip to content

Repository files navigation

logo

Phoenix Dataplane Service

Build PhoenixBuild mRPCOpen in Dev Containers

Documentation

Phoenix is a dataplane service which serves as a framework to develop and deploy various kinds of managed services.

The key features of Phoenix include:

Modular Plugin System: Phoenix provides an engine abstraction which, as the modular unit, can be developed, dynamically load, scheduled, and even be live upgraded with minimal disruption to user applications.

High-performance Networking: Phoenix offers managed access to networking devices while exposing a user-friendly API.

Policy Manageability: Phoenix supports application-layer policies which can be specified by infrastructure administers to gain visibility and control user application behaviors.

Getting Started

Building Phoenix

  1. Clone the repo and its submodules.
$ git clone git@github.com:phoenix-dataplane/phoenix.git --recursive
  1. Install required packages. Make sure you have libibverbs, librdmacm, libnuma, protoc, libclang, and cmake available on your system. Additionally, you need to have rustup and cargo-make installed. For Ubuntu 22.04, you can use the following commands:
$ sudo apt update
$ sudo apt install libclang-dev libnuma-dev librdmacm-dev libibverbs-dev protobuf-compiler cmake
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ cargo install cargo-make

Alternatively, if you already have VS Code and Docker installed, click the badge above or here to start.

  1. Build and run PhoenixOS service.
$ cargo make

By default, cargo make will build the dev-test-flow target. You can inspect and customize the stages of this workflow in Makefile.toml. Use cargo make run-phoenixos to start the service after building.

You can also manually execute each step in the dev-test-flow.

PhoenixOS without any plugins is just an empty control plane. Next, you can build and load some useful plugins and run a few user applications.

Building and Running mRPC

mRPC is the first experimental feature on Phoenix. To build and deploy mRPC plugins, and run PhoenixOS, follow these steps:

$ cd experimental/mrpc
$ cat load-mrpc-plugins.toml >> ../../phoenix.toml
$ cargo make

Ensure that exactly one instance of PhoenixOS is running on each server.

Note: If you have multiple machines, update the destination address in experimental/mrpc/examples/rpc_hello/src/client.rs to your server address.

Next, build the rpc_echo example:

$ cargo build --release --workspace -p rpc_echo

You can also build all mRPC examples using:

$ cargo make build-mrpc-examples

Note: building phoenixos and its plugins requires the plugins to link with a prebuilt set of phoenix crates. This is currently done by tools/phoenix_cargo and the entire workflow is handled by cargo-make. However, building user libraries and apps does not require that. We can still use cargo.

Running mRPC examples

You can run the examples manually by

$ cargo rr -p rpc_echo --bin rpc_echo_server
# In a seperate terminal
$ cargo rr -p rpc_echo --bin rpc_echo_client

Note: If you have multiple machines, we provide a launcher to help with running the examples:

$ cd ../../benchmark
# Follow the README under benchmark directory and update config.toml
$ cargo rr --bin launcher -- --benchmark benchmark/rpc_echo.toml

You can explore the set of mRPC user applications in experimental/mrpc/examples.

Learning More

Documentation

License

Phoenix is licensed under the Apache-2.0 license.

About

Phoenix dataplane system service

Resources

Stars

55 stars

Watchers

8 watching

Forks

Releases

Packages

Used by

Contributors

Languages