diff --git a/examples/evpn_router/.formatter.exs b/examples/evpn_router/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/examples/evpn_router/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/examples/evpn_router/.gitignore b/examples/evpn_router/.gitignore new file mode 100644 index 0000000..c37ad57 --- /dev/null +++ b/examples/evpn_router/.gitignore @@ -0,0 +1,25 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where 3rd-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +evpn_router-*.tar + +/priv/ \ No newline at end of file diff --git a/examples/evpn_router/README.md b/examples/evpn_router/README.md new file mode 100644 index 0000000..a61ef93 --- /dev/null +++ b/examples/evpn_router/README.md @@ -0,0 +1,21 @@ +# EvpnRouter + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `evpn_router` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:evpn_router, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at [https://hexdocs.pm/evpn_router](https://hexdocs.pm/evpn_router). + diff --git a/examples/evpn_router/config/config.exs b/examples/evpn_router/config/config.exs new file mode 100644 index 0000000..cec476b --- /dev/null +++ b/examples/evpn_router/config/config.exs @@ -0,0 +1,30 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +use Mix.Config + +# This configuration is loaded before any dependency and is restricted +# to this project. If another project depends on this project, this +# file won't be loaded nor affect the parent project. For this reason, +# if you want to provide default values for your application for +# 3rd-party users, it should be done in your "mix.exs" file. + +# You can configure your application as: +# +# config :evpn_router, key: :value +# +# and access this configuration in your application as: +# +# Application.get_env(:evpn_router, :key) +# +# You can also configure a 3rd-party app: +# +# config :logger, level: :info +# + +# It is also possible to import configuration files, relative to this +# directory. For example, you can emulate configuration per environment +# by uncommenting the line below and defining dev.exs, test.exs and such. +# Configuration from the imported file will override the ones defined +# here (which is why it is important to import them last). +# +# import_config "#{Mix.env()}.exs" diff --git a/examples/evpn_router/lib/evpn_router.ex b/examples/evpn_router/lib/evpn_router.ex new file mode 100644 index 0000000..ff3b8e5 --- /dev/null +++ b/examples/evpn_router/lib/evpn_router.ex @@ -0,0 +1,18 @@ +defmodule EvpnRouter do + @moduledoc """ + Documentation for EvpnRouter. + """ + + @doc """ + Hello world. + + ## Examples + + iex> EvpnRouter.hello() + :world + + """ + def hello do + :world + end +end diff --git a/examples/evpn_router/lib/evpn_router/application.ex b/examples/evpn_router/lib/evpn_router/application.ex new file mode 100644 index 0000000..a0281d4 --- /dev/null +++ b/examples/evpn_router/lib/evpn_router/application.ex @@ -0,0 +1,20 @@ +defmodule EvpnRouter.Application do + # See https://hexdocs.pm/elixir/Application.html + # for more information on OTP Applications + @moduledoc false + + use Application + + def start(_type, _args) do + # List all child processes to be supervised + children = [ + # Starts a worker by calling: EvpnRouter.Worker.start_link(arg) + # {EvpnRouter.Worker, arg}, + ] + + # See https://hexdocs.pm/elixir/Supervisor.html + # for other strategies and supported options + opts = [strategy: :one_for_one, name: EvpnRouter.Supervisor] + Supervisor.start_link(children, opts) + end +end diff --git a/examples/evpn_router/lib/evpn_router/go_bgp/native_utils.ex b/examples/evpn_router/lib/evpn_router/go_bgp/native_utils.ex new file mode 100644 index 0000000..261fde7 --- /dev/null +++ b/examples/evpn_router/lib/evpn_router/go_bgp/native_utils.ex @@ -0,0 +1,8 @@ +defmodule EvpnRouter.GoBGP.NativeUtils do + use Rustler, otp_app: :evpn_router, crate: :evpn_router + + @spec get_route_family(String.t()) :: {:ok, non_neg_integer()} + def get_route_family(_p0) do + {:error, :nif_error} + end +end diff --git a/examples/evpn_router/mix.exs b/examples/evpn_router/mix.exs new file mode 100644 index 0000000..9b34b36 --- /dev/null +++ b/examples/evpn_router/mix.exs @@ -0,0 +1,38 @@ +defmodule EvpnRouter.MixProject do + use Mix.Project + + def project do + [ + app: :evpn_router, + version: "0.1.0", + elixir: "~> 1.7", + start_permanent: Mix.env() == :prod, + compilers: [:rustler] ++ Mix.compilers, + rustler_crates: rustler_crates(), + deps: deps() + ] + end + + def application do + [ + extra_applications: [:logger, :grpc, :tres], + mod: {EvpnRouter.Application, []} + ] + end + + defp deps do + [ + {:tres, path: "../../../tres"}, + {:rustler, github: "hansihe/rustler", sparse: "rustler_mix"}, + {:grpc, github: "tony612/grpc-elixir"}, + {:ranch, "~> 1.6.0", override: true}, + ] + end + + defp rustler_crates do + [evpn_router: [path: "native/evpn_router", mode: rustc_mode(Mix.env)]] + end + + defp rustc_mode(:prod), do: :release + defp rustc_mode(_), do: :debug +end diff --git a/examples/evpn_router/mix.lock b/examples/evpn_router/mix.lock new file mode 100644 index 0000000..f8c80a5 --- /dev/null +++ b/examples/evpn_router/mix.lock @@ -0,0 +1,38 @@ +%{ + "bbmustache": {:hex, :bbmustache, "1.3.0", "2010adae78830992a4c69680115ecd7d475dd03a72c076bbaddccbf2d4b32035", [:rebar3], [], "hexpm"}, + "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"}, + "cf": {:hex, :cf, "0.2.2", "7f2913fff90abcabd0f489896cfeb0b0674f6c8df6c10b17a83175448029896c", [:rebar3], [], "hexpm"}, + "cowboy": {:git, "https://github.com/ninenines/cowboy.git", "c998673eb009da2ea4dc0e6ef0332534cf679cc4", []}, + "cowlib": {:hex, :cowlib, "2.6.0", "8aa629f81a0fc189f261dc98a42243fa842625feea3c7ec56c48f4ccdb55490f", [:rebar3], [], "hexpm"}, + "cth_readable": {:hex, :cth_readable, "1.4.0", "f51362e3d365b14de5aed7e98166e0643f38d004af9750369d8f90e9f470fcc7", [:rebar3], [{:cf, "~>0.2.1", [hex: :cf, repo: "hexpm", optional: false]}], "hexpm"}, + "dep_http2_client": {:git, "https://github.com/Bluehouse-Technology/http2_client", "8a6faf3ef1e0f3bb480d52d34ef5181258e99302", [branch: "master"]}, + "elixir_make": {:hex, :elixir_make, "0.1.0", "b5a40367dce0ec15db916a9bcdfee189eebb536a13b814246e2551bcdb0c7031", [:mix], [], "hexpm"}, + "eovsdb": {:git, "https://github.com/shun159/eovsdb.git", "1ff1572708d72fd25631c681f2102407903252a3", [branch: "master"]}, + "erlang_gobgp": {:git, "https://github.com/vasu-dasari/erlang-gobgp.git", "126bf98608a7f70ba78a81573b6861f95e8a2348", [branch: "master"]}, + "erlware_commons": {:hex, :erlware_commons, "1.1.0", "f69f3d96044c2a9e735ccd76f469fec5fc851797e5fe23115698b4edc072191b", [:rebar3], [{:cf, "~>0.3", [hex: :cf, repo: "hexpm", optional: false]}], "hexpm"}, + "erlydtl": {:git, "https://github.com/erlydtl/erlydtl.git", "032746b8068f367eb63923cb6f8b2095065015b9", []}, + "eunit_formatters": {:hex, :eunit_formatters, "0.5.0", "6a9133943d36a465d804c1c5b6e6839030434b8879c5600d7ddb5b3bad4ccb59", [:rebar3], [], "hexpm"}, + "ffi": {:git, "https://github.com/joshnuss/elixir-ffi.git", "b93183f27bd5d2cd6ce4c2c282801d4176e9462f", []}, + "getopt": {:hex, :getopt, "1.0.1", "c73a9fa687b217f2ff79f68a3b637711bb1936e712b521d8ce466b29cbf7808a", [:rebar3], [], "hexpm"}, + "gobgp": {:git, "https://github.com/vasu-dasari/erlang-gobgp.git", "126bf98608a7f70ba78a81573b6861f95e8a2348", [branch: "master"]}, + "goldrush": {:git, "git://github.com/DeadZen/goldrush.git", "212299233c7e7eb63a97be2777e1c05ebaa58dbe", [tag: "0.1.8"]}, + "gpb": {:hex, :gpb, "4.4.0", "cfd81b167f804b5a3720d7867530f6700e54644284431e4e14e032139c205251", [:make, :rebar], [], "hexpm"}, + "grpc": {:git, "https://github.com/tony612/grpc-elixir.git", "c0eaa61d789f5c5b9e3c2f4c213944bebaf2c72c", []}, + "grpc_client": {:git, "https://github.com/vasu-dasari/grpc_client.git", "930384100ddff5fb05ffb058f11b33df878c304f", [tag: "master"]}, + "grpc_lib": {:git, "https://github.com/Bluehouse-Technology/grpc_lib", "a77686b55b60b052d6c7cd927d04dde429bbdabf", [branch: "master"]}, + "gun": {:hex, :gun, "1.3.0", "18e5d269649c987af95aec309f68a27ffc3930531dd227a6eaa0884d6684286e", [:rebar3], [{:cowlib, "~> 2.6.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm"}, + "jsone": {:git, "https://github.com/sile/jsone.git", "b23d312a5ed051ea7ad0989a9f2cb1a9c3f9a502", [tag: "1.4.6"]}, + "lager": {:git, "https://github.com/basho/lager.git", "8187757388c9adc915379caaab36a2f2ca26e944", [tag: "3.2.1"]}, + "nifty": {:git, "https://github.com/parapluu/nifty.git", "1534f6877d694db87e3c4a5c3cd46ee62a393245", []}, + "proper": {:git, "https://github.com/proper-testing/proper.git", "16f9f7cb181f41ffb882c4a31052275dfad16ee1", [branch: "master"]}, + "protobuf": {:hex, :protobuf, "0.5.4", "2e1b8eec211aff034ad8a14e3674220b0158bfb9a3c7128ac9d2a1ed1b3724d3", [:mix], [], "hexpm"}, + "providers": {:hex, :providers, "1.7.0", "bbf730563914328ec2511d205e6477a94831db7297de313b3872a2b26c562eab", [:rebar3], [{:getopt, "1.0.1", [hex: :getopt, repo: "hexpm", optional: false]}], "hexpm"}, + "ranch": {:hex, :ranch, "1.6.2", "6db93c78f411ee033dbb18ba8234c5574883acb9a75af0fb90a9b82ea46afa00", [:rebar3], [], "hexpm"}, + "rebar": {:git, "https://github.com/erlang/rebar3.git", "33eb505573170ff8bf77d6b4758c88a75bf772d8", [tag: "3.5.3"]}, + "rebar3": {:git, "https://github.com/erlang/rebar3.git", "33eb505573170ff8bf77d6b4758c88a75bf772d8", [tag: "3.5.3"]}, + "relx": {:hex, :relx, "3.24.4", "2132f0abfa93db3177e66768db5a3d4141d4683bb4864b9dd4452ee7123ded07", [:rebar3], [{:bbmustache, "1.0.4", [hex: :bbmustache, repo: "hexpm", optional: false]}, {:cf, "0.2.2", [hex: :cf, repo: "hexpm", optional: false]}, {:erlware_commons, "1.0.5", [hex: :erlware_commons, repo: "hexpm", optional: false]}, {:getopt, "1.0.1", [hex: :getopt, repo: "hexpm", optional: false]}, {:providers, "1.7.0", [hex: :providers, repo: "hexpm", optional: false]}], "hexpm"}, + "rustler": {:git, "https://github.com/hansihe/rustler.git", "d44bdbca496c761af7201ebad61a188092712ab1", [sparse: "rustler_mix"]}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.3", "6c49665d4326e26cd4a5b7bd54aa442b33dadfb7c5d59a0d0cd0bf5534bbfbd7", [:make, :mix, :rebar3], [], "hexpm"}, + "sync": {:git, "https://github.com/rustyio/sync.git", "9b207f7396e8c037c66db1b3ca8f7b0338586397", [branch: "master"]}, + "uuid": {:git, "https://github.com/avtobiff/erlang-uuid.git", "585c2474afb4a597ae8c8bf6d21e5a9c73f18e0b", [tag: "v0.5.0"]}, +} diff --git a/examples/evpn_router/native/evpn_router/.gitignore b/examples/evpn_router/native/evpn_router/.gitignore new file mode 100644 index 0000000..f2f9e58 --- /dev/null +++ b/examples/evpn_router/native/evpn_router/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock \ No newline at end of file diff --git a/examples/evpn_router/native/evpn_router/Cargo.toml b/examples/evpn_router/native/evpn_router/Cargo.toml new file mode 100644 index 0000000..b04da08 --- /dev/null +++ b/examples/evpn_router/native/evpn_router/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "evpn_router" +version = "0.1.0" +build = "build.rs" + + +[lib] +name = "evpn_router" +path = "src/lib.rs" +crate-type = ["dylib"] + +[dependencies] +rustler = { git = "https://github.com/hansihe/rustler", branch = "remove_nif_from_types"} +rustler_codegen = { git = "https://github.com/hansihe/rustler", branch = "remove_nif_from_types"} +bufstream = "0.1.2" +lazy_static = "1.0.0" +libc = "0.2" \ No newline at end of file diff --git a/examples/evpn_router/native/evpn_router/build.rs b/examples/evpn_router/native/evpn_router/build.rs new file mode 100644 index 0000000..44fbb16 --- /dev/null +++ b/examples/evpn_router/native/evpn_router/build.rs @@ -0,0 +1,3 @@ +fn main() { + println!("cargo:rustc-link-search=../evpn_router"); +} diff --git a/examples/evpn_router/native/evpn_router/libgobgp.h b/examples/evpn_router/native/evpn_router/libgobgp.h new file mode 100644 index 0000000..0ff0c1c --- /dev/null +++ b/examples/evpn_router/native/evpn_router/libgobgp.h @@ -0,0 +1,96 @@ +/* Code generated by cmd/cgo; DO NOT EDIT. */ + +/* package command-line-arguments */ + + +#line 1 "cgo-builtin-prolog" + +#include /* for ptrdiff_t below */ + +#ifndef GO_CGO_EXPORT_PROLOGUE_H +#define GO_CGO_EXPORT_PROLOGUE_H + +typedef struct { const char *p; ptrdiff_t n; } _GoString_; + +#endif + +/* Start of preamble from import "C" comments. */ + + +#line 18 "path.go" + typedef struct { + char *value; + int len; + } buf; + + typedef struct path_t { + buf nlri; + buf** path_attributes; + int path_attributes_len; + int path_attributes_cap; + } path; + extern path* new_path(); + extern void free_path(path*); + extern int append_path_attribute(path*, int, char*); + extern buf* get_path_attribute(path*, int); + +#line 1 "cgo-generated-wrapper" + + +/* End of preamble from import "C" comments. */ + + +/* Start of boilerplate cgo prologue. */ +#line 1 "cgo-gcc-export-header-prolog" + +#ifndef GO_CGO_PROLOGUE_H +#define GO_CGO_PROLOGUE_H + +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoInt64 GoInt; +typedef GoUint64 GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef float _Complex GoComplex64; +typedef double _Complex GoComplex128; + +/* + static assertion to make sure the file is being used on architecture + at least with matching size of GoInt. +*/ +typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; + +typedef _GoString_ GoString; +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; + +#endif + +/* End of boilerplate cgo prologue. */ + +#ifdef __cplusplus +extern "C" { +#endif + + +extern int get_route_family(char* p0); + +extern path* serialize_path(int p0, char* p1); + +extern char* decode_path(path* p0); + +extern char* decode_capabilities(buf* p0); + +#ifdef __cplusplus +} +#endif diff --git a/examples/evpn_router/native/evpn_router/libgobgp.so b/examples/evpn_router/native/evpn_router/libgobgp.so new file mode 100755 index 0000000..20fd78e Binary files /dev/null and b/examples/evpn_router/native/evpn_router/libgobgp.so differ diff --git a/examples/evpn_router/native/evpn_router/src/gobgp_utils.rs b/examples/evpn_router/native/evpn_router/src/gobgp_utils.rs new file mode 100644 index 0000000..eae1278 --- /dev/null +++ b/examples/evpn_router/native/evpn_router/src/gobgp_utils.rs @@ -0,0 +1,82 @@ +/* automatically generated by rust-bindgen */ + +extern crate libc; +use self::libc::{c_void, c_int, c_longlong, c_char, size_t}; + +#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] +#[repr(C)] +pub struct __BindgenComplex { + pub re: T, + pub im: T, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct max_align_t { + pub __clang_max_align_nonce1: c_longlong, + pub __bindgen_padding_0: u64, + pub __clang_max_align_nonce2: f64, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _GoString_ { + pub p: *const c_char, + pub n: isize, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct buf { + pub value: *mut c_char, + pub len: c_int, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct path_t { + pub nlri: buf, + pub path_attributes: *mut *mut buf, + pub path_attributes_len: c_int, + pub path_attributes_cap: c_int, +} + +pub type path = path_t; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct GoInterface { + pub t: *mut c_void, + pub v: *mut c_void, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct GoSlice { + pub data: *mut c_void, + pub len: c_longlong, + pub cap: c_longlong, +} + +#[link(name = "gobgp")] +extern { + pub fn new_path() -> *mut path; + + pub fn free_path(arg1: *mut path); + + pub fn append_path_attribute( + arg1: *mut path, + arg2: c_int, + arg3: *mut c_char, + ) -> c_int; + + pub fn get_path_attribute(arg1: *mut path, arg2: c_int) -> *mut buf; + + pub fn get_route_family(p0: *mut String) -> u32; + + pub fn serialize_path(p0: u32, p1: *mut String) -> *mut path; + + pub fn decode_path(p0: *mut path) -> *mut c_char; + + pub fn decode_capabilities(p0: *mut buf) -> *mut c_char; +} diff --git a/examples/evpn_router/native/evpn_router/src/lib.rs b/examples/evpn_router/native/evpn_router/src/lib.rs new file mode 100644 index 0000000..f8112c9 --- /dev/null +++ b/examples/evpn_router/native/evpn_router/src/lib.rs @@ -0,0 +1,40 @@ +#![allow(bad_style, missing_copy_implementations, improper_ctypes)] + +mod gobgp_utils; +use gobgp_utils::get_route_family; +use gobgp_utils::serialize_path; + +use gobgp_utils::{buf, path_t}; + +#[macro_use] extern crate rustler; +#[macro_use] extern crate lazy_static; + +use rustler::{Env, Term, NifResult, Encoder}; + +mod atoms { + rustler_atoms! { + atom ok; + } +} + +rustler_export_nifs!( + "Elixir.EvpnRouter.GoBGP.NativeUtils", + [("nif_get_route_family", 1, nif_get_route_family), + ("serialize_path", 2, nif_serialize_path)], + None +); + +pub fn nif_get_route_family<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult> { + let mut p0: String = args[0].decode()?; + let family = unsafe { get_route_family(&mut p0) }; + + Ok((atoms::ok(), family).encode(env)) +} + +pub fn nif_serialize_path<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult> { + let mut family: u32 = args[0].decode()?; + let mut path_str: String = args[1].decode()?; + let mut path: path_t = unsafe { serialize_path(&mut family, &mut path_str) } + + Ok((atoms::ok(), )) +} diff --git a/examples/evpn_router/test/evpn_router_test.exs b/examples/evpn_router/test/evpn_router_test.exs new file mode 100644 index 0000000..8c40ecb --- /dev/null +++ b/examples/evpn_router/test/evpn_router_test.exs @@ -0,0 +1,8 @@ +defmodule EvpnRouterTest do + use ExUnit.Case + doctest EvpnRouter + + test "greets the world" do + assert EvpnRouter.hello() == :world + end +end diff --git a/examples/evpn_router/test/test_helper.exs b/examples/evpn_router/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/examples/evpn_router/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/examples/evpn_router/vendor/README.md b/examples/evpn_router/vendor/README.md new file mode 100644 index 0000000..bad4dd5 --- /dev/null +++ b/examples/evpn_router/vendor/README.md @@ -0,0 +1,5 @@ +Notes on Third Party Software Packages +====================================== + +Software packages found in this directory are not part of this example. Each software +packages is distributed under the terms and conditions described in the package. diff --git a/examples/evpn_router/vendor/gobgp_1.33_linux_amd64.tar.gz b/examples/evpn_router/vendor/gobgp_1.33_linux_amd64.tar.gz new file mode 100644 index 0000000..c30c23c Binary files /dev/null and b/examples/evpn_router/vendor/gobgp_1.33_linux_amd64.tar.gz differ