SlideShare a Scribd company logo
1 of 35
Download to read offline
Rust-DPDK
Internet Week 2017 Software Router/Switch BoF
Nov 29, 2017
Masaru OKI
DPDK
 Data Plane Development Kit
 http://dpdk.org/
 ユーザ空間で高速パケット処理を実現するライブラリ。BSD License.
 C言語のAPIとして提供される。
 基本的にLinux向け。(一部機能が未提供だが)FreeBSDでも動作する。
 バージョン番号は年.月。(1.8.0や2.2.0は旧命名規則。かなり古い)
 16.11.3がLTS(Long Term Support)
 17.05 → 17.08 → 17.11 → と続いていく。
2
Kernel moduleはGPL
DPDKが使われているところ
 高速なパケット転送を必要としている部分に採用されている。
 基本的に、どれもC言語で実装されている。
 Pktgen-dpdk
パケットジェネレータ。
 Soft patch panel (spp)
ソフトウェアパッチパネル。
 ovs-dpdk
Open vSwitch。DPDK対応版としてビルドすると使える。
 Lagopus vswitch
OpenFlow 1.3対応ソフトウェアスイッチ。
 FD.io VPP
Vector Packet Processing platform. L2/L3処理エンジン。
3
モチベーション
 DPDKアプリケーションの大半はC言語で書かれている。
 C言語はシンプルだが困った点も多い。
 現代のモダンな言語と比較すると素朴すぎ。(e.g.メモリ管理は自己責任)
 ライブラリが管理されていない、更新など全部手でやる。
 C++で書くことも可能だが、C++は複雑すぎる。
 他のモダンな言語で書けばメンテが楽になりそう。
 Lagopus routerではGo言語が使われている。
 他のプログラミング言語でDPDKを扱えないか?
4
検討した言語(いわゆるbetter C)
 C# (ゲームエンジンのUnityで使われている)
 https://docs.microsoft.com/ja-jp/dotnet/csharp/
 Go (GoBGPだとかZebra2.0やLagopus routerがGo言語で書かれている)
 https://golang.org/
 Swift (Objective-Cの代替、iOSアプリが書ける)
 https://swift.org/
 Kotlin (Javaの代替、Androidアプリが書ける)
 https://kotlinlang.org/
 Rust (初期はMozillaによって開発された)
 https://www.rust-lang.org/
5
Rust?
 https://www.rust-lang.org/
 Rustは速度、安全性、並行性の3つのゴールにフォーカスしたシステム
プログラミング言語。
 スクリプト言語ではなく、ネイティブコードにコンパイルする。
 コンパイラのバックエンドはLLVM。
 いろいろなOS(Linux, *BSD, Windows, macOS, …)に対応。
 多様なCPU(x86_64, i386, ARM, ARM64, MIPS, MIPS64, PPC, PPC64, …)
に対応。
 Rustで書かれたOSが存在する: RedoxOS, intermezzOS, Tock
6
Rustのhello, world
 拡張子は .rs
 % cat hello.rs
fn main() {
println!(”hello, world.”);
}
% rustc hello.rs
% ./hello
hello, world.
%
rustc –emit asm hello.rs
とすればasm出力が得られる。
7
既存のDPDKのRustバインディング
 すでにいくつか実装があった
 https://github.com/libpnet/rust-dpdk
 https://github.com/flier/rust-dpdk
 https://github.com/ANLAB-KAIST/rust-dpdk
対応状況 libpnet/rust-dpdk flier/rust-dpdk ANLAB-KAIST/rust-dpdk
対応DPDK ver. 1.8.0 不明 不明
最終更新 2015年1月 2016年6月 2017年4月
ビルド方法 make cargo build cargo build
サポート状況 bindgenでの変換のみ、
inline未対応、サンプルプロ
グラムなし(実質動かない)
サンプルプログラム多数。
l2fwdの各coreで動かす関数
がC言語
サンプルプログラムなし
8
既存の実装をあてにできず、自作する
 ベースはlibpnet/rust-dpdk
 Rustの安定版でまだ提供されていない機能を使う。
 C言語のThread Local Storageへのアクセス: nightly buildなら対応。
 Bindingは、bindgenというツールで自動生成。
 ツールを別途インストールする必要はなし。
 Rust標準のcargoコマンドでビルドできる。
 RustらしくするAPIについては手で追加コードを用意。
 https://github.com/iMasaruOki/rust-dpdk
9
DPDKを使って各coreでhello(C言語)
 int
hello(void *arg) {
printf(“hello lcore %d¥n”, rte_lcore_id());
return 0;
}
int
main(int argc, char *argv[]) {
rte_eal_init(argc, argv);
rte_eal_mp_remote_launch(hello, NULL, CALL_MASTER);
rte_eal_mp_wait_lcore();
return 0;
}
10
各コアで動くスレッド
DPDKの初期化
各コアでhello()を実行
RustでDPDK hello (iMasaruOki版)
 extern crate dpdk;
use std::os::raw::c_void;
unsafe extern "C" fn hello_thread(_arg: *mut c_void)
-> i32 {
println!("Hello! lcore {}", dpdk::lcore::id());
0
}
fn main() {
unsafe {
let _ = dpdk::eal::init(std::env::args());
let callback_arg: *mut c_void = std::mem::zeroed();
dpdk::eal::mp_remote_launch(hello_thread,
callback_arg, true);
dpdk::eal::mp_wait_lcore();
}
}
11
各コアで動くスレッド。
DPDKから呼ばれるのでextern ”C”が必要。
DPDKの初期化
各コアでhello_thread()を実行
外部のコードを取り込む
RustでDPDK hello ビルドと実行
 $ pwd
/home/masaru/src/rust-dpdk/examples/dpdk-hello
$ cargo +nightly build
(ビルドログは省略)
$ sudo ./target/debug/dpdk-hello -cf -n2
EAL: Detected 8 lcore(s)
EAL: No free hugepages reported in hugepages-1048576kB
EAL: Probing VFIO support...
Hello! lcore 1
Hello! lcore 0
Hello! lcore 2
Hello! lcore 3
$
12
DPDKアプリはsudo必須
Rust-DPDK iMasaruOki版のステータス
 DPDK 17.11対応
 wrapperを作成したAPIはまだごく一部
 マルチコア動作を確認
 l2fwd相当のサンプルを作成、パケット転送できることを確認
netns: ns1
114.0.0.1/24
netns: ns2
114.0.0.2/24
netns: ns3
114.0.0.3/24
dpdk-l2fwd
tap i/f
13
dpdk-l2fwd デモ
14
今後に向けて
 DPDKのrte_flowやCrypto APIなど対応させていきたい
 Lagopus vSwitchのサブセットが作れないか検討中
 使えそうなcrate(Pythonのpipのように外部ライブラリを管理できる)
 rust_ofp: OpenFlow 1.0 プロトコルを提供
 pnet: Rust向けパケット処理フレームワーク
 grpc: gRPCサポート
 toml: TOMLサポート
 Tom's Obvious, Minimal Language
 いわゆるINIファイルのような記述で設定を表現する
15
おまけ: 他言語でのDPDK対応
 https://github.com/libmoon/libmoon
LuaJIT
 https://github.com/feiskyer/dpdk-go
Go言語(forkもありました)
 https://github.com/intel-go/yanff
Go言語で抽象化APIを提供
 https://github.com/FlowForwarding/edpdk
erlangでDPDK PMDを利用
 https://software.intel.com/en-us/articles/minimize-nodejs-io-
bottlenecks
LKLを使ってJavaScriptからDPDKを呼ぶという記事
 https://github.com/P4ELTE/t4p4s
bindingではないが、 DPDKを使うバイナリを出力するP4言語コンパイラ
16
予備
17
おまけ2: Rustの解説
 詳細は公式ドキュメントを参照。
 https://www.rust-lang.org/ja-JP/documentation.html
 書き方の例を見てまねるにはRust by Exampleが有用。
 https://rustbyexample.com/
 記法のおおまかな紹介
 コメントは // … か /* … */
 行志向ではなく、Cと同じくセミコロンで区切る。
 スレッドサポートはライブラリで。スレッド間IPCも、同期処理系もライブラリ。
 マクロはあるけどCプリプロセッサではない。
 extern ”C” 宣言すればC言語のライブラリを呼び出すことができる。
18
Rustのインストールと更新
 curl https://sh.rustup.rs –sSf | sh
 $HOME/.cargo/binにインストールされる。
 rustc: コンパイラ
 cargo: パッケージマネージャ
 rustup: ツールチェインのインストーラ/アップデータ
 必要な環境変数は$HOME/.cargo/envの実行で設定される。
 sudoしない。ユーザーごと。
 Windowsの場合はインストーラを実行。
 コンパイラを最新版にするときはrustup update
19
ビルドには(makeではなく)cargoを使う
 % pwd
/tmp/hello
% mkdir src
% mv hello.rs src/main.rs
% cargo init
Created library project
% cargo run
Compiling hello v0.1.0 (file:///tmp/hello)
Finished dev [unoptimized + debuginfo] target(s) in 0.xx secs
Running `target/debug/hello`
hello, world.
%
シンプルなCargo.tomlを生成。
必要に応じて手直しする。
コマンド 意味
cargo run コンパイルして即実行
cargo build ビルドのみ
cargo test テストコードを実行
cargo doc ドキュメントを生成
cargo clean target/を削除
20
簡単な紹介
 ファンクションはfnで定義する。(hello.rsでみたとおり)
 別のソースから参照されるものはpub fnと書く。
 変数や値の型はu8, u16, u32, i8, i16, i32など。後ろに書く。
 fn testfunc(arg: u32) -> u32 {
let a: u32 = 1;
let b = a + 1;
let a = b + arg;
let mut c = a + b;
c = c * 2;
a + b + c
}
Cでいうところの
uint32_t testfunc(uint32_t arg)
型宣言して初期値を代入、変更不可能
右辺の型がわかるので省略(型推論)
新しいaを宣言(以前のaは参照できない)
cはmutable(変更できる)
最後に式を書くとリターン値になる
Cのようにreturn a + b + c;
と書いてもよい
21
型いろいろ
 u8, u16, u32, u64: 符号なし整数
 i8, i16, i32, i64: 符号あり整数
 bool: 真偽値 (true or false)
 usize: 符号なしでサイズをあらわす(配列の添え字はこれ)
 isize: 符号ありサイズ(ポインタのオフセットはこれ)
 f32, f64: 浮動小数
 char: Unicode文字
 String, Vector, HashMapが標準ライブラリとして用意される
 これらは特別な宣言なしにビルトイン型と同じように使える
 type your_type = u64; などと書けばC言語でいうtypedefが可能
22
型キャスト
 式 as 型 でキャストできる。
 符号なし整数でもサイズが違うと別の型。
 違う型の値どうしの演算をする場合キャストが必要。
 let shortval: u16 = 3;
let longval: u32 = 5;
let ans = shortval + longval;
shortval as u32 + longval 型が違うのでこの記述は
エラーになりビルドできない
キャストして
型を合わせて演算する
23
条件分岐
 if a == b {
println!(”equal”);
} else {
println!(”a == {} but b == {}”, a, b);
}
match a {
1 => println!(”one”),
2 => println!(”two”),
_ => println!(”other”),
}
Cのswitch caseでの
defaultに相当
24
ループ
 forはあるが、Cとだいぶ異なる記法。 (Python等に似ている)
let values: [u32; 5] = [ 3, 5, 7, 9, 11];
for value in values.iter() {
…
}
 for i in 0..10 { … } // 0~9 (10ではない)
 whileはCなどと同様。
while !done { // done != trueと同じ
…
}
 loop { … } は while true { … } と同じ。永久ループ。
 break; や continue; はCと同様。ラベルを付けてそこに飛ぶことも可能。
 ’label1: while !done {
loop {
if a == b { continue ’label1; }
}
}
25
配列、ポインタ、参照
 ポインタは通常使わ(れ)ない。
 Cでいう構造体ポインタからのメンバ参照foo->barの->は存在しない。
 (*foo).barと書く。
 C言語ライブラリとつなぐ際はポインタを多用する(せざるを得ない)。
 配列
let array: [u32; 3] = [ 1, 2, 3];
 配列先頭のポインタ
let ptr = array.as_ptr(); // Cではuint32_t *ptr = array;
let mut_ptr: *mut u32; // 型推論しない場合は例えばこう
 ポインタから配列の中身を参照
let val = *ptr.offset(1); // Cでは*(ptr + 1)で、値は2
 Rust言語では通常変数のアクセスを追跡して安全を保障する。
 ポインタの参照は安全ではないためunsafeという指定が必要。
 unsafe fn foo () { … } など関数単位の指定が多いようだ。
26
structとimpl (trait)
 structを定義し、それに対してfnを定義することができる。
 traitと呼ばれる。C++のclassに対するメンバ関数のようなもの。
 struct Foo {
v: u32,
}
impl Foo {
fn add(&mut self, val: u32) {
self.v = self.v + val;
}
}
fn main() {
let mut testfoo = Foo { v: 10 };
testfoo.add(2);
println!(”{}”, testfoo.v); // 12
}
27
Generic functions
 C++のテンプレート相当。
 テンプレートのように foo<T>などと定義し、foo<u32>など指定して使う。
 定義(traitを使う)
impl <T> Vec<T> {
pub fn new() -> Vec<T> {
…
}
…
}
 使用例
let mut vec: Vec<i32> = Vec::new();
28
Rustのライブラリ、crate
 crateとは「木箱」という意味。
 言語上はextern crate 名前; で引き込む。
 モジュール名::サブモジュール名::型などと書いて参照
 use mod::submod::type; などとすれば単にtypeで参照できる
 たとえばHTTP実装 Hyper https://hyper.rs/
 stdから始まるものは標準で引き込まれるのでextern crate不要。
 std::thread, std::option, std::syncなど
29
crateの引き込み方
 パッケージシステム上はCargo.tomlに記述を加える。
 例
[dependencies]
libc = ”0.2”
my_crate = { git = ”https://github.com/...”, rev = ”8ef654d…” }
 https://crates.io/ から取得する。
 有用な定番ものから開発途上のものまで1万以上が登録されている。
 git = https://github.com/... と書けばgithubから取得できる。
 rev = ”1075f4e…”など書けばcommit指定ができる。rev指定がない場合はmasterを取得する。
 cargo buildあるいはcargo run実行でソースを取得しビルドする。
 一度取得したら以後はローカルのものを使用。
 通常は静的リンクになるので出来上がるバイナリは大きくなる。
 取得元の更新内容と同期(再取得)するにはcargo updateを実行する。
30
C言語ライブラリの呼び出し方
 extern ”C”をつけてRust風にfn宣言すれば呼び出せる。
 structもRust風に定義する。
 例
extern ”C” pub fn your_c_func(arg: u32) -> u32;
 ポインタにアクセスするものはだいたいunsafe
use ::std::os::raw::c_void;
unsafe extern “C” pub fn unsafe_func(arg: c_void);
 Foeign Function Interface (FFI)と呼んでいる。
 リンクするには、 Cargo.tomlと同じ場所にbuild.rsを用意する。
 build.rsの例
fn main() {
// libfooをリンク
println!(”cargo:rustc-link-lib=foo”);
}
31
Cライブラリのbindingを自動生成
 bindgenというツールで自動生成できる。
 https://rust-lang-nursery.github.io/rust-bindgen/
 コマンドラインツールとして使う場合は、cargo install bindgenでインストール。
 C言語のヘッダを読ませ、Rustソース(extern ”C”の塊)を出力する。
 シェル等からbindgenコマンドを呼び出すのでもいいが、
crateになってるのでbuild.rsに書くのがおすすめ。(Cargo.tomlへの追加も忘れずに)
 例
extern crate bindgen;
use std::path::PathBuf;
fn main() {
let bindings = bindgen::Builder::default()
.header(”foo.h”)
.generate();
bindings.write_to_file(PathBuf::from(”src/foo.rs”));
}
32
bindgenでの生成例
C言語
 ulimit.h (一部)
 enum
{
UL_GETFSIZE = 1,
UL_SETFSIZE,
__UL_GETMAXBRK,
__UL_GETOPENMAX
};
extern long int ulimit (int __cmd, …);
Rust (bindgenで生成)
 /* automatically generated by rust-bindgen */
pub const UL_GETFSIZE: _bindgen_ty_1 = _bindgen_ty_1::UL_GETFSIZE;
pub const UL_SETFSIZE: _bindgen_ty_1 = _bindgen_ty_1::UL_SETFSIZE;
pub const __UL_GETMAXBRK: _bindgen_ty_1 = _bindgen_ty_1::__UL_GETMAXBRK;
pub const __UL_GETOPENMAX: _bindgen_ty_1 = _bindgen_ty_1::__UL_GETOPENMAX;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
UL_GETFSIZE = 1,
UL_SETFSIZE = 2,
__UL_GETMAXBRK = 3,
__UL_GETOPENMAX = 4,
}
extern "C" {
pub fn ulimit(__cmd: ::std::os::raw::c_int, ...)
-> ::std::os::raw::c_long;
}
33
Rustは使いやすいか?
 注: 私見です
 C++と違い、明示的に書いたコードだけが動くので追いかけやすい
 Goと違いスレッドの扱いやスレッド間通信が言語に隠蔽されない
 Goと違いgitのcommitの指定が標準で可能
 cgoみたいなコメントにゴリゴリ書く汚いスタイルではなくextern ”C”
 型チェックが強力で、雑に書けるCより面倒だが安心感がある
 エラー発生時にもしかして?と表示してくれるのは初心者には助かる
 GCはない
 言語とライブラリの境界がはっきりしている
 かなりC言語に近い感覚で書けるので、Cがわかるならとっつきやすい
 シンプルさに重きを置いたbetter C
34
おまけ3: DPDK APIをRustから呼ぶ方法
 bindgenを使えば楽勝?
→実はbindgenで対応できないものがある
 ヘッダファイルで定義されるinline functionに未対応
 extern ”C”を吐き出すだけで実体を定義しないので、現状しかたない
 回避方法
 -fno-inlineでライブラリを再コンパイル(実際には意味がない)
 自前でRustで書き直す
 inline functionを呼び出すwrapperをC言語で書き、同時にリンクする
35

More Related Content

What's hot

CDNの仕組み(JANOG36)
CDNの仕組み(JANOG36)CDNの仕組み(JANOG36)
CDNの仕組み(JANOG36)J-Stream Inc.
 
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介Preferred Networks
 
高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!masakazu matsubara
 
eStargzイメージとlazy pullingによる高速なコンテナ起動
eStargzイメージとlazy pullingによる高速なコンテナ起動eStargzイメージとlazy pullingによる高速なコンテナ起動
eStargzイメージとlazy pullingによる高速なコンテナ起動Kohei Tokunaga
 
Linux packet-forwarding
Linux packet-forwardingLinux packet-forwarding
Linux packet-forwardingMasakazu Asama
 
tcpdumpとtcpreplayとtcprewriteと他。
tcpdumpとtcpreplayとtcprewriteと他。tcpdumpとtcpreplayとtcprewriteと他。
tcpdumpとtcpreplayとtcprewriteと他。(^-^) togakushi
 
LinuxのFull ticklessを試してみた
LinuxのFull ticklessを試してみたLinuxのFull ticklessを試してみた
LinuxのFull ticklessを試してみたHiraku Toyooka
 
10GbE時代のネットワークI/O高速化
10GbE時代のネットワークI/O高速化10GbE時代のネットワークI/O高速化
10GbE時代のネットワークI/O高速化Takuya ASADA
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践Yoshifumi Kawai
 
詳説データベース輪読会: 分散合意その2
詳説データベース輪読会: 分散合意その2詳説データベース輪読会: 分散合意その2
詳説データベース輪読会: 分散合意その2Sho Nakazono
 
DockerコンテナでGitを使う
DockerコンテナでGitを使うDockerコンテナでGitを使う
DockerコンテナでGitを使うKazuhiro Suga
 
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)NTT DATA Technology & Innovation
 
2015年度GPGPU実践プログラミング 第6回 パフォーマンス解析ツール
2015年度GPGPU実践プログラミング 第6回 パフォーマンス解析ツール2015年度GPGPU実践プログラミング 第6回 パフォーマンス解析ツール
2015年度GPGPU実践プログラミング 第6回 パフォーマンス解析ツール智啓 出川
 
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.kiki utagawa
 
プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜京大 マイコンクラブ
 
RustによるGPUプログラミング環境
RustによるGPUプログラミング環境RustによるGPUプログラミング環境
RustによるGPUプログラミング環境KiyotomoHiroyasu
 

What's hot (20)

CDNの仕組み(JANOG36)
CDNの仕組み(JANOG36)CDNの仕組み(JANOG36)
CDNの仕組み(JANOG36)
 
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
[GTCJ2018]CuPy -NumPy互換GPUライブラリによるPythonでの高速計算- PFN奥田遼介
 
高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!
 
eStargzイメージとlazy pullingによる高速なコンテナ起動
eStargzイメージとlazy pullingによる高速なコンテナ起動eStargzイメージとlazy pullingによる高速なコンテナ起動
eStargzイメージとlazy pullingによる高速なコンテナ起動
 
Linux packet-forwarding
Linux packet-forwardingLinux packet-forwarding
Linux packet-forwarding
 
tcpdumpとtcpreplayとtcprewriteと他。
tcpdumpとtcpreplayとtcprewriteと他。tcpdumpとtcpreplayとtcprewriteと他。
tcpdumpとtcpreplayとtcprewriteと他。
 
LinuxのFull ticklessを試してみた
LinuxのFull ticklessを試してみたLinuxのFull ticklessを試してみた
LinuxのFull ticklessを試してみた
 
10GbE時代のネットワークI/O高速化
10GbE時代のネットワークI/O高速化10GbE時代のネットワークI/O高速化
10GbE時代のネットワークI/O高速化
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
 
詳説データベース輪読会: 分散合意その2
詳説データベース輪読会: 分散合意その2詳説データベース輪読会: 分散合意その2
詳説データベース輪読会: 分散合意その2
 
Marp入門
Marp入門Marp入門
Marp入門
 
Marp Tutorial
Marp TutorialMarp Tutorial
Marp Tutorial
 
Consistent hash
Consistent hashConsistent hash
Consistent hash
 
DockerコンテナでGitを使う
DockerコンテナでGitを使うDockerコンテナでGitを使う
DockerコンテナでGitを使う
 
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
 
2015年度GPGPU実践プログラミング 第6回 パフォーマンス解析ツール
2015年度GPGPU実践プログラミング 第6回 パフォーマンス解析ツール2015年度GPGPU実践プログラミング 第6回 パフォーマンス解析ツール
2015年度GPGPU実践プログラミング 第6回 パフォーマンス解析ツール
 
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
 
プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜
 
Gpu vs fpga
Gpu vs fpgaGpu vs fpga
Gpu vs fpga
 
RustによるGPUプログラミング環境
RustによるGPUプログラミング環境RustによるGPUプログラミング環境
RustによるGPUプログラミング環境
 

Similar to Rust-DPDK

pkgsrc とは何か? - よもやま話
pkgsrc とは何か? - よもやま話pkgsrc とは何か? - よもやま話
pkgsrc とは何か? - よもやま話Akio OBATA
 
OpenSolaris Printing Environment
OpenSolaris Printing EnvironmentOpenSolaris Printing Environment
OpenSolaris Printing EnvironmentNaruhiko Ogasawara
 
pkgsrc とは何か? - よもやま話
pkgsrc とは何か? - よもやま話pkgsrc とは何か? - よもやま話
pkgsrc とは何か? - よもやま話Akio OBATA
 
Ruby でパケットパーサを作ろう
Ruby でパケットパーサを作ろうRuby でパケットパーサを作ろう
Ruby でパケットパーサを作ろうYasuhito Takamiya
 
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜Hideki Takase
 
つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜
つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜
つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜Hideki Takase
 
20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux20170527 inside .NET Core on Linux
20170527 inside .NET Core on LinuxTakayoshi Tanaka
 
2011.09.18 v7から始めるunix まとめ
2011.09.18 v7から始めるunix まとめ2011.09.18 v7から始めるunix まとめ
2011.09.18 v7から始めるunix まとめMakiko Konoshima
 
CouchDB JP & BigCouch
CouchDB JP & BigCouchCouchDB JP & BigCouch
CouchDB JP & BigCouchYohei Sasaki
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Ransui Iso
 
ふつうのLinuxプログラミング
ふつうのLinuxプログラミングふつうのLinuxプログラミング
ふつうのLinuxプログラミングShuhei KONDO
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0Kiwamu Okabe
 
qemuのriscv64にDebianを入れてみた
qemuのriscv64にDebianを入れてみたqemuのriscv64にDebianを入れてみた
qemuのriscv64にDebianを入れてみたKazuhiro Nishiyama
 
Flutterを体験してみませんか
Flutterを体験してみませんかFlutterを体験してみませんか
Flutterを体験してみませんかcch-robo
 
Linux Kernel Seminar in tripodworks
Linux Kernel Seminar in tripodworksLinux Kernel Seminar in tripodworks
Linux Kernel Seminar in tripodworkstripodworks
 
Lagopus Router v19.07.1
Lagopus Router v19.07.1Lagopus Router v19.07.1
Lagopus Router v19.07.1Tomoya Hibi
 
Rubyで創るOpenFlowネットワーク - LLまつり
Rubyで創るOpenFlowネットワーク - LLまつりRubyで創るOpenFlowネットワーク - LLまつり
Rubyで創るOpenFlowネットワーク - LLまつりYuya Rin
 

Similar to Rust-DPDK (20)

Pdp11 on-fpga
Pdp11 on-fpgaPdp11 on-fpga
Pdp11 on-fpga
 
pkgsrc とは何か? - よもやま話
pkgsrc とは何か? - よもやま話pkgsrc とは何か? - よもやま話
pkgsrc とは何か? - よもやま話
 
OpenSolaris Printing Environment
OpenSolaris Printing EnvironmentOpenSolaris Printing Environment
OpenSolaris Printing Environment
 
pkgsrc とは何か? - よもやま話
pkgsrc とは何か? - よもやま話pkgsrc とは何か? - よもやま話
pkgsrc とは何か? - よもやま話
 
Ruby でパケットパーサを作ろう
Ruby でパケットパーサを作ろうRuby でパケットパーサを作ろう
Ruby でパケットパーサを作ろう
 
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
 
つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜
つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜
つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜
 
20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux
 
2011.09.18 v7から始めるunix まとめ
2011.09.18 v7から始めるunix まとめ2011.09.18 v7から始めるunix まとめ
2011.09.18 v7から始めるunix まとめ
 
CouchDB JP & BigCouch
CouchDB JP & BigCouchCouchDB JP & BigCouch
CouchDB JP & BigCouch
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
 
Rust-DPDK
Rust-DPDKRust-DPDK
Rust-DPDK
 
ふつうのLinuxプログラミング
ふつうのLinuxプログラミングふつうのLinuxプログラミング
ふつうのLinuxプログラミング
 
How to run P4 BMv2
How to run P4 BMv2How to run P4 BMv2
How to run P4 BMv2
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0
 
qemuのriscv64にDebianを入れてみた
qemuのriscv64にDebianを入れてみたqemuのriscv64にDebianを入れてみた
qemuのriscv64にDebianを入れてみた
 
Flutterを体験してみませんか
Flutterを体験してみませんかFlutterを体験してみませんか
Flutterを体験してみませんか
 
Linux Kernel Seminar in tripodworks
Linux Kernel Seminar in tripodworksLinux Kernel Seminar in tripodworks
Linux Kernel Seminar in tripodworks
 
Lagopus Router v19.07.1
Lagopus Router v19.07.1Lagopus Router v19.07.1
Lagopus Router v19.07.1
 
Rubyで創るOpenFlowネットワーク - LLまつり
Rubyで創るOpenFlowネットワーク - LLまつりRubyで創るOpenFlowネットワーク - LLまつり
Rubyで創るOpenFlowネットワーク - LLまつり
 

More from Masaru Oki

NetBSD移植の昔話
NetBSD移植の昔話NetBSD移植の昔話
NetBSD移植の昔話Masaru Oki
 
Lagopusとvagrant
LagopusとvagrantLagopusとvagrant
LagopusとvagrantMasaru Oki
 
OpenFlowでいろんなプロトコルを 話そうとするとどうなるか
OpenFlowでいろんなプロトコルを 話そうとするとどうなるかOpenFlowでいろんなプロトコルを 話そうとするとどうなるか
OpenFlowでいろんなプロトコルを 話そうとするとどうなるかMasaru Oki
 
今よりも少し(?)昔、 Windowsを作ろうとした話
今よりも少し(?)昔、 Windowsを作ろうとした話今よりも少し(?)昔、 Windowsを作ろうとした話
今よりも少し(?)昔、 Windowsを作ろうとした話Masaru Oki
 
Onieで遊んでみようとした話
Onieで遊んでみようとした話Onieで遊んでみようとした話
Onieで遊んでみようとした話Masaru Oki
 
GPD WINが来た!
GPD WINが来た!GPD WINが来た!
GPD WINが来た!Masaru Oki
 
新生Lagopus2017(仮称)
新生Lagopus2017(仮称)新生Lagopus2017(仮称)
新生Lagopus2017(仮称)Masaru Oki
 
Lagopus as open flow hybrid switch 実践編
Lagopus as open flow hybrid switch 実践編Lagopus as open flow hybrid switch 実践編
Lagopus as open flow hybrid switch 実践編Masaru Oki
 
LagopusでPPPoEを使えるか考えてみた件
LagopusでPPPoEを使えるか考えてみた件LagopusでPPPoEを使えるか考えてみた件
LagopusでPPPoEを使えるか考えてみた件Masaru Oki
 
Lagopus どれだけ速いのか
Lagopus どれだけ速いのかLagopus どれだけ速いのか
Lagopus どれだけ速いのかMasaru Oki
 
Ryu+Lagopusで OpenFlowの動きを見てみよう
Ryu+Lagopusで OpenFlowの動きを見てみようRyu+Lagopusで OpenFlowの動きを見てみよう
Ryu+Lagopusで OpenFlowの動きを見てみようMasaru Oki
 
Lagopus match improvements
Lagopus match improvementsLagopus match improvements
Lagopus match improvementsMasaru Oki
 
Open flow tunnel extension on lagopus vswitch
Open flow tunnel extension on lagopus vswitchOpen flow tunnel extension on lagopus vswitch
Open flow tunnel extension on lagopus vswitchMasaru Oki
 
Lagopus as open flow hybrid switch
Lagopus as open flow hybrid switchLagopus as open flow hybrid switch
Lagopus as open flow hybrid switchMasaru Oki
 
Net bsd advent calendar 2015 bpf
Net bsd advent calendar 2015 bpfNet bsd advent calendar 2015 bpf
Net bsd advent calendar 2015 bpfMasaru Oki
 
Using rump on NetBSD 7.0
Using rump on NetBSD 7.0Using rump on NetBSD 7.0
Using rump on NetBSD 7.0Masaru Oki
 
Rumpを使ってみる
Rumpを使ってみるRumpを使ってみる
Rumpを使ってみるMasaru Oki
 
FreeBSD jail+vnetと戯れた話
FreeBSD jail+vnetと戯れた話FreeBSD jail+vnetと戯れた話
FreeBSD jail+vnetと戯れた話Masaru Oki
 

More from Masaru Oki (20)

NetBSD移植の昔話
NetBSD移植の昔話NetBSD移植の昔話
NetBSD移植の昔話
 
Lagopusとvagrant
LagopusとvagrantLagopusとvagrant
Lagopusとvagrant
 
OpenFlowでいろんなプロトコルを 話そうとするとどうなるか
OpenFlowでいろんなプロトコルを 話そうとするとどうなるかOpenFlowでいろんなプロトコルを 話そうとするとどうなるか
OpenFlowでいろんなプロトコルを 話そうとするとどうなるか
 
今よりも少し(?)昔、 Windowsを作ろうとした話
今よりも少し(?)昔、 Windowsを作ろうとした話今よりも少し(?)昔、 Windowsを作ろうとした話
今よりも少し(?)昔、 Windowsを作ろうとした話
 
Onieで遊んでみようとした話
Onieで遊んでみようとした話Onieで遊んでみようとした話
Onieで遊んでみようとした話
 
GPD WINが来た!
GPD WINが来た!GPD WINが来た!
GPD WINが来た!
 
新生Lagopus2017(仮称)
新生Lagopus2017(仮称)新生Lagopus2017(仮称)
新生Lagopus2017(仮称)
 
Lagopus as open flow hybrid switch 実践編
Lagopus as open flow hybrid switch 実践編Lagopus as open flow hybrid switch 実践編
Lagopus as open flow hybrid switch 実践編
 
LagopusでPPPoEを使えるか考えてみた件
LagopusでPPPoEを使えるか考えてみた件LagopusでPPPoEを使えるか考えてみた件
LagopusでPPPoEを使えるか考えてみた件
 
Lagopus どれだけ速いのか
Lagopus どれだけ速いのかLagopus どれだけ速いのか
Lagopus どれだけ速いのか
 
Lagopus 0.2.7
Lagopus 0.2.7Lagopus 0.2.7
Lagopus 0.2.7
 
Ryu+Lagopusで OpenFlowの動きを見てみよう
Ryu+Lagopusで OpenFlowの動きを見てみようRyu+Lagopusで OpenFlowの動きを見てみよう
Ryu+Lagopusで OpenFlowの動きを見てみよう
 
Lagopus match improvements
Lagopus match improvementsLagopus match improvements
Lagopus match improvements
 
Lagopus 0.2.4
Lagopus 0.2.4Lagopus 0.2.4
Lagopus 0.2.4
 
Open flow tunnel extension on lagopus vswitch
Open flow tunnel extension on lagopus vswitchOpen flow tunnel extension on lagopus vswitch
Open flow tunnel extension on lagopus vswitch
 
Lagopus as open flow hybrid switch
Lagopus as open flow hybrid switchLagopus as open flow hybrid switch
Lagopus as open flow hybrid switch
 
Net bsd advent calendar 2015 bpf
Net bsd advent calendar 2015 bpfNet bsd advent calendar 2015 bpf
Net bsd advent calendar 2015 bpf
 
Using rump on NetBSD 7.0
Using rump on NetBSD 7.0Using rump on NetBSD 7.0
Using rump on NetBSD 7.0
 
Rumpを使ってみる
Rumpを使ってみるRumpを使ってみる
Rumpを使ってみる
 
FreeBSD jail+vnetと戯れた話
FreeBSD jail+vnetと戯れた話FreeBSD jail+vnetと戯れた話
FreeBSD jail+vnetと戯れた話
 

Rust-DPDK

  • 1. Rust-DPDK Internet Week 2017 Software Router/Switch BoF Nov 29, 2017 Masaru OKI
  • 2. DPDK  Data Plane Development Kit  http://dpdk.org/  ユーザ空間で高速パケット処理を実現するライブラリ。BSD License.  C言語のAPIとして提供される。  基本的にLinux向け。(一部機能が未提供だが)FreeBSDでも動作する。  バージョン番号は年.月。(1.8.0や2.2.0は旧命名規則。かなり古い)  16.11.3がLTS(Long Term Support)  17.05 → 17.08 → 17.11 → と続いていく。 2 Kernel moduleはGPL
  • 3. DPDKが使われているところ  高速なパケット転送を必要としている部分に採用されている。  基本的に、どれもC言語で実装されている。  Pktgen-dpdk パケットジェネレータ。  Soft patch panel (spp) ソフトウェアパッチパネル。  ovs-dpdk Open vSwitch。DPDK対応版としてビルドすると使える。  Lagopus vswitch OpenFlow 1.3対応ソフトウェアスイッチ。  FD.io VPP Vector Packet Processing platform. L2/L3処理エンジン。 3
  • 4. モチベーション  DPDKアプリケーションの大半はC言語で書かれている。  C言語はシンプルだが困った点も多い。  現代のモダンな言語と比較すると素朴すぎ。(e.g.メモリ管理は自己責任)  ライブラリが管理されていない、更新など全部手でやる。  C++で書くことも可能だが、C++は複雑すぎる。  他のモダンな言語で書けばメンテが楽になりそう。  Lagopus routerではGo言語が使われている。  他のプログラミング言語でDPDKを扱えないか? 4
  • 5. 検討した言語(いわゆるbetter C)  C# (ゲームエンジンのUnityで使われている)  https://docs.microsoft.com/ja-jp/dotnet/csharp/  Go (GoBGPだとかZebra2.0やLagopus routerがGo言語で書かれている)  https://golang.org/  Swift (Objective-Cの代替、iOSアプリが書ける)  https://swift.org/  Kotlin (Javaの代替、Androidアプリが書ける)  https://kotlinlang.org/  Rust (初期はMozillaによって開発された)  https://www.rust-lang.org/ 5
  • 6. Rust?  https://www.rust-lang.org/  Rustは速度、安全性、並行性の3つのゴールにフォーカスしたシステム プログラミング言語。  スクリプト言語ではなく、ネイティブコードにコンパイルする。  コンパイラのバックエンドはLLVM。  いろいろなOS(Linux, *BSD, Windows, macOS, …)に対応。  多様なCPU(x86_64, i386, ARM, ARM64, MIPS, MIPS64, PPC, PPC64, …) に対応。  Rustで書かれたOSが存在する: RedoxOS, intermezzOS, Tock 6
  • 7. Rustのhello, world  拡張子は .rs  % cat hello.rs fn main() { println!(”hello, world.”); } % rustc hello.rs % ./hello hello, world. % rustc –emit asm hello.rs とすればasm出力が得られる。 7
  • 8. 既存のDPDKのRustバインディング  すでにいくつか実装があった  https://github.com/libpnet/rust-dpdk  https://github.com/flier/rust-dpdk  https://github.com/ANLAB-KAIST/rust-dpdk 対応状況 libpnet/rust-dpdk flier/rust-dpdk ANLAB-KAIST/rust-dpdk 対応DPDK ver. 1.8.0 不明 不明 最終更新 2015年1月 2016年6月 2017年4月 ビルド方法 make cargo build cargo build サポート状況 bindgenでの変換のみ、 inline未対応、サンプルプロ グラムなし(実質動かない) サンプルプログラム多数。 l2fwdの各coreで動かす関数 がC言語 サンプルプログラムなし 8
  • 9. 既存の実装をあてにできず、自作する  ベースはlibpnet/rust-dpdk  Rustの安定版でまだ提供されていない機能を使う。  C言語のThread Local Storageへのアクセス: nightly buildなら対応。  Bindingは、bindgenというツールで自動生成。  ツールを別途インストールする必要はなし。  Rust標準のcargoコマンドでビルドできる。  RustらしくするAPIについては手で追加コードを用意。  https://github.com/iMasaruOki/rust-dpdk 9
  • 10. DPDKを使って各coreでhello(C言語)  int hello(void *arg) { printf(“hello lcore %d¥n”, rte_lcore_id()); return 0; } int main(int argc, char *argv[]) { rte_eal_init(argc, argv); rte_eal_mp_remote_launch(hello, NULL, CALL_MASTER); rte_eal_mp_wait_lcore(); return 0; } 10 各コアで動くスレッド DPDKの初期化 各コアでhello()を実行
  • 11. RustでDPDK hello (iMasaruOki版)  extern crate dpdk; use std::os::raw::c_void; unsafe extern "C" fn hello_thread(_arg: *mut c_void) -> i32 { println!("Hello! lcore {}", dpdk::lcore::id()); 0 } fn main() { unsafe { let _ = dpdk::eal::init(std::env::args()); let callback_arg: *mut c_void = std::mem::zeroed(); dpdk::eal::mp_remote_launch(hello_thread, callback_arg, true); dpdk::eal::mp_wait_lcore(); } } 11 各コアで動くスレッド。 DPDKから呼ばれるのでextern ”C”が必要。 DPDKの初期化 各コアでhello_thread()を実行 外部のコードを取り込む
  • 12. RustでDPDK hello ビルドと実行  $ pwd /home/masaru/src/rust-dpdk/examples/dpdk-hello $ cargo +nightly build (ビルドログは省略) $ sudo ./target/debug/dpdk-hello -cf -n2 EAL: Detected 8 lcore(s) EAL: No free hugepages reported in hugepages-1048576kB EAL: Probing VFIO support... Hello! lcore 1 Hello! lcore 0 Hello! lcore 2 Hello! lcore 3 $ 12 DPDKアプリはsudo必須
  • 13. Rust-DPDK iMasaruOki版のステータス  DPDK 17.11対応  wrapperを作成したAPIはまだごく一部  マルチコア動作を確認  l2fwd相当のサンプルを作成、パケット転送できることを確認 netns: ns1 114.0.0.1/24 netns: ns2 114.0.0.2/24 netns: ns3 114.0.0.3/24 dpdk-l2fwd tap i/f 13
  • 15. 今後に向けて  DPDKのrte_flowやCrypto APIなど対応させていきたい  Lagopus vSwitchのサブセットが作れないか検討中  使えそうなcrate(Pythonのpipのように外部ライブラリを管理できる)  rust_ofp: OpenFlow 1.0 プロトコルを提供  pnet: Rust向けパケット処理フレームワーク  grpc: gRPCサポート  toml: TOMLサポート  Tom's Obvious, Minimal Language  いわゆるINIファイルのような記述で設定を表現する 15
  • 16. おまけ: 他言語でのDPDK対応  https://github.com/libmoon/libmoon LuaJIT  https://github.com/feiskyer/dpdk-go Go言語(forkもありました)  https://github.com/intel-go/yanff Go言語で抽象化APIを提供  https://github.com/FlowForwarding/edpdk erlangでDPDK PMDを利用  https://software.intel.com/en-us/articles/minimize-nodejs-io- bottlenecks LKLを使ってJavaScriptからDPDKを呼ぶという記事  https://github.com/P4ELTE/t4p4s bindingではないが、 DPDKを使うバイナリを出力するP4言語コンパイラ 16
  • 18. おまけ2: Rustの解説  詳細は公式ドキュメントを参照。  https://www.rust-lang.org/ja-JP/documentation.html  書き方の例を見てまねるにはRust by Exampleが有用。  https://rustbyexample.com/  記法のおおまかな紹介  コメントは // … か /* … */  行志向ではなく、Cと同じくセミコロンで区切る。  スレッドサポートはライブラリで。スレッド間IPCも、同期処理系もライブラリ。  マクロはあるけどCプリプロセッサではない。  extern ”C” 宣言すればC言語のライブラリを呼び出すことができる。 18
  • 19. Rustのインストールと更新  curl https://sh.rustup.rs –sSf | sh  $HOME/.cargo/binにインストールされる。  rustc: コンパイラ  cargo: パッケージマネージャ  rustup: ツールチェインのインストーラ/アップデータ  必要な環境変数は$HOME/.cargo/envの実行で設定される。  sudoしない。ユーザーごと。  Windowsの場合はインストーラを実行。  コンパイラを最新版にするときはrustup update 19
  • 20. ビルドには(makeではなく)cargoを使う  % pwd /tmp/hello % mkdir src % mv hello.rs src/main.rs % cargo init Created library project % cargo run Compiling hello v0.1.0 (file:///tmp/hello) Finished dev [unoptimized + debuginfo] target(s) in 0.xx secs Running `target/debug/hello` hello, world. % シンプルなCargo.tomlを生成。 必要に応じて手直しする。 コマンド 意味 cargo run コンパイルして即実行 cargo build ビルドのみ cargo test テストコードを実行 cargo doc ドキュメントを生成 cargo clean target/を削除 20
  • 21. 簡単な紹介  ファンクションはfnで定義する。(hello.rsでみたとおり)  別のソースから参照されるものはpub fnと書く。  変数や値の型はu8, u16, u32, i8, i16, i32など。後ろに書く。  fn testfunc(arg: u32) -> u32 { let a: u32 = 1; let b = a + 1; let a = b + arg; let mut c = a + b; c = c * 2; a + b + c } Cでいうところの uint32_t testfunc(uint32_t arg) 型宣言して初期値を代入、変更不可能 右辺の型がわかるので省略(型推論) 新しいaを宣言(以前のaは参照できない) cはmutable(変更できる) 最後に式を書くとリターン値になる Cのようにreturn a + b + c; と書いてもよい 21
  • 22. 型いろいろ  u8, u16, u32, u64: 符号なし整数  i8, i16, i32, i64: 符号あり整数  bool: 真偽値 (true or false)  usize: 符号なしでサイズをあらわす(配列の添え字はこれ)  isize: 符号ありサイズ(ポインタのオフセットはこれ)  f32, f64: 浮動小数  char: Unicode文字  String, Vector, HashMapが標準ライブラリとして用意される  これらは特別な宣言なしにビルトイン型と同じように使える  type your_type = u64; などと書けばC言語でいうtypedefが可能 22
  • 23. 型キャスト  式 as 型 でキャストできる。  符号なし整数でもサイズが違うと別の型。  違う型の値どうしの演算をする場合キャストが必要。  let shortval: u16 = 3; let longval: u32 = 5; let ans = shortval + longval; shortval as u32 + longval 型が違うのでこの記述は エラーになりビルドできない キャストして 型を合わせて演算する 23
  • 24. 条件分岐  if a == b { println!(”equal”); } else { println!(”a == {} but b == {}”, a, b); } match a { 1 => println!(”one”), 2 => println!(”two”), _ => println!(”other”), } Cのswitch caseでの defaultに相当 24
  • 25. ループ  forはあるが、Cとだいぶ異なる記法。 (Python等に似ている) let values: [u32; 5] = [ 3, 5, 7, 9, 11]; for value in values.iter() { … }  for i in 0..10 { … } // 0~9 (10ではない)  whileはCなどと同様。 while !done { // done != trueと同じ … }  loop { … } は while true { … } と同じ。永久ループ。  break; や continue; はCと同様。ラベルを付けてそこに飛ぶことも可能。  ’label1: while !done { loop { if a == b { continue ’label1; } } } 25
  • 26. 配列、ポインタ、参照  ポインタは通常使わ(れ)ない。  Cでいう構造体ポインタからのメンバ参照foo->barの->は存在しない。  (*foo).barと書く。  C言語ライブラリとつなぐ際はポインタを多用する(せざるを得ない)。  配列 let array: [u32; 3] = [ 1, 2, 3];  配列先頭のポインタ let ptr = array.as_ptr(); // Cではuint32_t *ptr = array; let mut_ptr: *mut u32; // 型推論しない場合は例えばこう  ポインタから配列の中身を参照 let val = *ptr.offset(1); // Cでは*(ptr + 1)で、値は2  Rust言語では通常変数のアクセスを追跡して安全を保障する。  ポインタの参照は安全ではないためunsafeという指定が必要。  unsafe fn foo () { … } など関数単位の指定が多いようだ。 26
  • 27. structとimpl (trait)  structを定義し、それに対してfnを定義することができる。  traitと呼ばれる。C++のclassに対するメンバ関数のようなもの。  struct Foo { v: u32, } impl Foo { fn add(&mut self, val: u32) { self.v = self.v + val; } } fn main() { let mut testfoo = Foo { v: 10 }; testfoo.add(2); println!(”{}”, testfoo.v); // 12 } 27
  • 28. Generic functions  C++のテンプレート相当。  テンプレートのように foo<T>などと定義し、foo<u32>など指定して使う。  定義(traitを使う) impl <T> Vec<T> { pub fn new() -> Vec<T> { … } … }  使用例 let mut vec: Vec<i32> = Vec::new(); 28
  • 29. Rustのライブラリ、crate  crateとは「木箱」という意味。  言語上はextern crate 名前; で引き込む。  モジュール名::サブモジュール名::型などと書いて参照  use mod::submod::type; などとすれば単にtypeで参照できる  たとえばHTTP実装 Hyper https://hyper.rs/  stdから始まるものは標準で引き込まれるのでextern crate不要。  std::thread, std::option, std::syncなど 29
  • 30. crateの引き込み方  パッケージシステム上はCargo.tomlに記述を加える。  例 [dependencies] libc = ”0.2” my_crate = { git = ”https://github.com/...”, rev = ”8ef654d…” }  https://crates.io/ から取得する。  有用な定番ものから開発途上のものまで1万以上が登録されている。  git = https://github.com/... と書けばgithubから取得できる。  rev = ”1075f4e…”など書けばcommit指定ができる。rev指定がない場合はmasterを取得する。  cargo buildあるいはcargo run実行でソースを取得しビルドする。  一度取得したら以後はローカルのものを使用。  通常は静的リンクになるので出来上がるバイナリは大きくなる。  取得元の更新内容と同期(再取得)するにはcargo updateを実行する。 30
  • 31. C言語ライブラリの呼び出し方  extern ”C”をつけてRust風にfn宣言すれば呼び出せる。  structもRust風に定義する。  例 extern ”C” pub fn your_c_func(arg: u32) -> u32;  ポインタにアクセスするものはだいたいunsafe use ::std::os::raw::c_void; unsafe extern “C” pub fn unsafe_func(arg: c_void);  Foeign Function Interface (FFI)と呼んでいる。  リンクするには、 Cargo.tomlと同じ場所にbuild.rsを用意する。  build.rsの例 fn main() { // libfooをリンク println!(”cargo:rustc-link-lib=foo”); } 31
  • 32. Cライブラリのbindingを自動生成  bindgenというツールで自動生成できる。  https://rust-lang-nursery.github.io/rust-bindgen/  コマンドラインツールとして使う場合は、cargo install bindgenでインストール。  C言語のヘッダを読ませ、Rustソース(extern ”C”の塊)を出力する。  シェル等からbindgenコマンドを呼び出すのでもいいが、 crateになってるのでbuild.rsに書くのがおすすめ。(Cargo.tomlへの追加も忘れずに)  例 extern crate bindgen; use std::path::PathBuf; fn main() { let bindings = bindgen::Builder::default() .header(”foo.h”) .generate(); bindings.write_to_file(PathBuf::from(”src/foo.rs”)); } 32
  • 33. bindgenでの生成例 C言語  ulimit.h (一部)  enum { UL_GETFSIZE = 1, UL_SETFSIZE, __UL_GETMAXBRK, __UL_GETOPENMAX }; extern long int ulimit (int __cmd, …); Rust (bindgenで生成)  /* automatically generated by rust-bindgen */ pub const UL_GETFSIZE: _bindgen_ty_1 = _bindgen_ty_1::UL_GETFSIZE; pub const UL_SETFSIZE: _bindgen_ty_1 = _bindgen_ty_1::UL_SETFSIZE; pub const __UL_GETMAXBRK: _bindgen_ty_1 = _bindgen_ty_1::__UL_GETMAXBRK; pub const __UL_GETOPENMAX: _bindgen_ty_1 = _bindgen_ty_1::__UL_GETOPENMAX; #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum _bindgen_ty_1 { UL_GETFSIZE = 1, UL_SETFSIZE = 2, __UL_GETMAXBRK = 3, __UL_GETOPENMAX = 4, } extern "C" { pub fn ulimit(__cmd: ::std::os::raw::c_int, ...) -> ::std::os::raw::c_long; } 33
  • 34. Rustは使いやすいか?  注: 私見です  C++と違い、明示的に書いたコードだけが動くので追いかけやすい  Goと違いスレッドの扱いやスレッド間通信が言語に隠蔽されない  Goと違いgitのcommitの指定が標準で可能  cgoみたいなコメントにゴリゴリ書く汚いスタイルではなくextern ”C”  型チェックが強力で、雑に書けるCより面倒だが安心感がある  エラー発生時にもしかして?と表示してくれるのは初心者には助かる  GCはない  言語とライブラリの境界がはっきりしている  かなりC言語に近い感覚で書けるので、Cがわかるならとっつきやすい  シンプルさに重きを置いたbetter C 34
  • 35. おまけ3: DPDK APIをRustから呼ぶ方法  bindgenを使えば楽勝? →実はbindgenで対応できないものがある  ヘッダファイルで定義されるinline functionに未対応  extern ”C”を吐き出すだけで実体を定義しないので、現状しかたない  回避方法  -fno-inlineでライブラリを再コンパイル(実際には意味がない)  自前でRustで書き直す  inline functionを呼び出すwrapperをC言語で書き、同時にリンクする 35