sdn時代の開発よもやま話 - openflowとtrema

143
SDN時代の開発よもやま話OpenFlowTrema 高宮安仁 (Trema開発チーム) 12129日日曜日

Upload: yasuhito-takamiya

Post on 18-Jan-2015

12.922 views

Category:

Technology


12 download

DESCRIPTION

Googleや国内データセンターで実際に動いているSDNシステムの技術的説明から、OpenFlowの入門と応用、そしてTremaを使った実際の開発手法までをひととおり説明します。

TRANSCRIPT

Page 1: SDN時代の開発よもやま話 - OpenFlowとTrema

~SDN時代の開発よもやま話~

OpenFlowとTrema

高宮安仁 (Trema開発チーム)

12年12月9日日曜日

Page 2: SDN時代の開発よもやま話 - OpenFlowとTrema

FAQよくある疑問

12年12月9日日曜日

Page 3: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「何の役に立つの?」

12年12月9日日曜日

Page 4: SDN時代の開発よもやま話 - OpenFlowとTrema

世界で初めて、OpenFlow/SDN開発を扱った本

2013/1/8 発売

12年12月9日日曜日

Page 5: SDN時代の開発よもやま話 - OpenFlowとTrema

SDNとは

12年12月9日日曜日

Page 6: SDN時代の開発よもやま話 - OpenFlowとTrema

SDNとはプログラミング分野の1つ

12年12月9日日曜日

Page 7: SDN時代の開発よもやま話 - OpenFlowとTrema

SDNとはプログラミング分野の1つ

「GUIプログラミング」とかと同じ!

12年12月9日日曜日

Page 8: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlowとは

12年12月9日日曜日

Page 9: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlowとは

SDNのいち実装方式

12年12月9日日曜日

Page 10: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlowとは

SDNのいち実装方式

GtkとかCocoaとかと同じ!

12年12月9日日曜日

Page 11: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow

つまり

SDN12年12月9日日曜日

Page 12: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow

つまり

は純粋にソフトウェア開発の話。

SDN12年12月9日日曜日

Page 13: SDN時代の開発よもやま話 - OpenFlowとTrema

「評論もいーけど、動いて役に 立つもの作りません?」

MAKE12年12月9日日曜日

Page 14: SDN時代の開発よもやま話 - OpenFlowとTrema

http://itpro.nikkeibp.co.jp/article/NEWS/20120418/391401/

すでにバックボーンはOpenFlowで作っちゃた

Urs Hölzle

12年12月9日日曜日

Page 15: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「何の役に立つの?」→Googleの事例を解説

12年12月9日日曜日

Page 16: SDN時代の開発よもやま話 - OpenFlowとTrema

Googleのチャレンジ

•平均 PUE = 1.13

•年間アベイラビリティ = 99.984%

•処理するデータ量/day = 数十ペタ

最先端

12年12月9日日曜日

Page 17: SDN時代の開発よもやま話 - OpenFlowとTrema

Googleのチャレンジ

•平均 PUE = 1.13

•年間アベイラビリティ = 99.984%

•処理するデータ量/day = 数十ペタ

最先端

次のチャレンジはデータセンター

をつなぐネットワークだ!

12年12月9日日曜日

Page 18: SDN時代の開発よもやま話 - OpenFlowとTrema

WAN 回線のコスト日米間(4.8Tbps、1万km)=320億円

12年12月9日日曜日

Page 19: SDN時代の開発よもやま話 - OpenFlowとTrema

WAN 回線のコスト日米間(4.8Tbps、1万km)=320億円

回線を追加せずに、

既存のを有効活用したい

12年12月9日日曜日

Page 20: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

どれだけ流せる?

12年12月9日日曜日

Page 21: SDN時代の開発よもやま話 - OpenFlowとTrema

従来のルーティング

• ルータは自律分散で動く• 宛先に対して必ず最短路を選択• 帯域の使用量は加味してくれない

12年12月9日日曜日

Page 22: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

集中

ヒマ?

12年12月9日日曜日

Page 23: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

理想

12年12月9日日曜日

Page 24: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

10Gbps

6Gbps

帯域は?

12年12月9日日曜日

Page 25: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

10Gbps

6Gbps

?12年12月9日日曜日

Page 26: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

どう分ける?

12年12月9日日曜日

Page 27: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

TEサーバ

12年12月9日日曜日

Page 28: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

TEサーバ空き帯域の収集

12年12月9日日曜日

Page 29: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

TEサーバ空き帯域の収集 帯域の

割り当て

12年12月9日日曜日

Page 30: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

TEサーバ

12年12月9日日曜日

Page 31: SDN時代の開発よもやま話 - OpenFlowとTrema

DC DC

DC

TEサーバ

12年12月9日日曜日

Page 32: SDN時代の開発よもやま話 - OpenFlowとTrema

DC

TEサーバ

OpenFlowスイッチ

BGPルータ BGP処理部

コントローラ

12年12月9日日曜日

Page 33: SDN時代の開発よもやま話 - OpenFlowとTrema

DC

TEサーバ

OpenFlowスイッチ

BGPルータ BGP処理部

コントローラ経路情報

12年12月9日日曜日

Page 34: SDN時代の開発よもやま話 - OpenFlowとTrema

DC

TEサーバ

OpenFlowスイッチ

BGPルータ BGP処理部

コントローラ経路情報

トラフィック情報

12年12月9日日曜日

Page 35: SDN時代の開発よもやま話 - OpenFlowとTrema

DC

TEサーバ

OpenFlowスイッチ

BGPルータ BGP処理部

コントローラ経路情報

トラフィック情報

12年12月9日日曜日

Page 36: SDN時代の開発よもやま話 - OpenFlowとTrema

DC

TEサーバ

OpenFlowスイッチ

BGPルータ BGP処理部

コントローラ経路情報

経路制御

トラフィック情報

12年12月9日日曜日

Page 37: SDN時代の開発よもやま話 - OpenFlowとTrema

DC

TEサーバ

OpenFlowスイッチ

BGPルータ BGP処理部

コントローラ経路情報

経路制御

トラフィック情報

12年12月9日日曜日

Page 38: SDN時代の開発よもやま話 - OpenFlowとTrema

Google WANの利用率

ほぼ100%使い切り

12年12月9日日曜日

Page 39: SDN時代の開発よもやま話 - OpenFlowとTrema

DC

TEサーバ

OpenFlowスイッチ

BGPルータ BGP処理部

コントローラ

12年12月9日日曜日

Page 40: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「どういう仕組み?」

12年12月9日日曜日

Page 41: SDN時代の開発よもやま話 - OpenFlowとTrema

2分で分かるOpenFlow

12年12月9日日曜日

Page 42: SDN時代の開発よもやま話 - OpenFlowとTrema

従来のスイッチ

フローテーブル

ファームウェア領域

パケットの転送ルール

制御するソフトウェア

12年12月9日日曜日

Page 43: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

OpenFlowプロトコル

ソフトウェア

ハードウェア

フローテーブル

12年12月9日日曜日

Page 44: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

フローテーブル

転送ルールを参照速い

12年12月9日日曜日

Page 45: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

フローテーブル

転送ルールを参照速い

知らないパケット

12年12月9日日曜日

Page 46: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

フローテーブル

転送ルールを参照速い

知らないパケット

フローテーブルの更新

12年12月9日日曜日

Page 47: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

フローテーブル

転送ルールを参照速い

知らないパケット

フローテーブルの更新遅い

12年12月9日日曜日

Page 48: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「何がうれしいの?」

12年12月9日日曜日

Page 49: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlowのうれしさ

12年12月9日日曜日

Page 50: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlowのうれしさ

•ソフトウェアによる高い自由度

12年12月9日日曜日

Page 51: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlowのうれしさ

•ソフトウェアによる高い自由度

•システム連携と自動化

12年12月9日日曜日

Page 52: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlowのうれしさ

•ソフトウェアによる高い自由度

•システム連携と自動化

•ソフトウェア開発手法をネットワークに適用できる

12年12月9日日曜日

Page 53: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

フローテーブル

Ruby, Python, C++,Java,...好きな言語で書ける

OpenFlowプロトコル

(e.g., VLANの上限)

既存のプロトコルに縛られない

12年12月9日日曜日

Page 54: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

フローテーブル

TEサーバ ミドル DB

自由に連携

12年12月9日日曜日

Page 55: SDN時代の開発よもやま話 - OpenFlowとTrema

PaxosChubby

GFS

データセンター

12年12月9日日曜日

Page 56: SDN時代の開発よもやま話 - OpenFlowとTrema

PaxosChubby

GFS

データセンター

コントローラ

フローテーブル

12年12月9日日曜日

Page 57: SDN時代の開発よもやま話 - OpenFlowとTrema

PaxosChubby

GFS

データセンター

コントローラ

フローテーブル

12年12月9日日曜日

Page 58: SDN時代の開発よもやま話 - OpenFlowとTrema

ソフトウェア手法の応用

12年12月9日日曜日

Page 59: SDN時代の開発よもやま話 - OpenFlowとTrema

ソフトウェア手法の応用

•ネットワークを段階的に反復構築(アジャイル)

12年12月9日日曜日

Page 60: SDN時代の開発よもやま話 - OpenFlowとTrema

ソフトウェア手法の応用

•ネットワークを段階的に反復構築(アジャイル)

•ネットワークのテスト(各種テスト、テストドリブン)

12年12月9日日曜日

Page 61: SDN時代の開発よもやま話 - OpenFlowとTrema

ソフトウェア手法の応用

•ネットワークを段階的に反復構築(アジャイル)

•ネットワークのテスト(各種テスト、テストドリブン)

•バージョン管理や巻き戻し(git などのバージョン管理ツール)

12年12月9日日曜日

Page 62: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「フローテーブルで 何ができるの?」

12年12月9日日曜日

Page 63: SDN時代の開発よもやま話 - OpenFlowとTrema

12年12月9日日曜日

Page 64: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

転送

スイッチ

パケットの宛先MACアドレス→出力ポート

12年12月9日日曜日

Page 65: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

転送

スイッチ(トラフィックモニタ)

流量

トラフィック情報

12年12月9日日曜日

Page 66: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

ルータ

転送書き換え

送信元・宛先MACアドレスを書き換え

12年12月9日日曜日

Page 67: SDN時代の開発よもやま話 - OpenFlowとTrema

12年12月9日日曜日

Page 68: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラ

ロードバランサ

転送書き換え

トラフィック量に応じて転送先を調整

流量

トラフィック情報

バックエンドサーバ

12年12月9日日曜日

Page 69: SDN時代の開発よもやま話 - OpenFlowとTrema

帯域を目一杯使う

転送 転送

転送 転送

転送 転送

DC DC

12年12月9日日曜日

Page 70: SDN時代の開発よもやま話 - OpenFlowとTrema

レプリケーション

分岐

分岐

DC

DC

分岐

DC

DC

DC

12年12月9日日曜日

Page 71: SDN時代の開発よもやま話 - OpenFlowとTrema

ネットワークA

コントローラ

パッチパネル

転送

ネットワークB所属するネットワーク

をソフトウェアで切り替え12年12月9日日曜日

Page 72: SDN時代の開発よもやま話 - OpenFlowとTrema

ネットワークA

コントローラ

パッチパネル

転送

ネットワークB所属するネットワーク

をソフトウェアで切り替え12年12月9日日曜日

Page 73: SDN時代の開発よもやま話 - OpenFlowとTrema

ネットワークA

コントローラ

パッチパネル

転送

ネットワークB所属するネットワーク

をソフトウェアで切り替え12年12月9日日曜日

Page 74: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「どう作るの?」

12年12月9日日曜日

Page 75: SDN時代の開発よもやま話 - OpenFlowとTrema

主なOpenFlow

プログラミングフレームワーク

•Trema (Ruby)

•POX (Python)

•NOX (C++)

•Floodlight (Java)

12年12月9日日曜日

Page 76: SDN時代の開発よもやま話 - OpenFlowとTrema

バージョン対応状況

12年12月9日日曜日

Page 77: SDN時代の開発よもやま話 - OpenFlowとTrema

1.0 1.1 1.2 1.3

バージョン対応状況

12年12月9日日曜日

Page 78: SDN時代の開発よもやま話 - OpenFlowとTrema

1.0 1.1 1.2 1.3

Floodlight

Trema

NOX

POX

バージョン対応状況

12年12月9日日曜日

Page 79: SDN時代の開発よもやま話 - OpenFlowとTrema

1.0 1.1 1.2 1.3

TremaEdgeFloodlight

Trema

NOX

POX

バージョン対応状況

12年12月9日日曜日

Page 80: SDN時代の開発よもやま話 - OpenFlowとTrema

12年12月9日日曜日

Page 81: SDN時代の開発よもやま話 - OpenFlowとTrema

12年12月9日日曜日

Page 82: SDN時代の開発よもやま話 - OpenFlowとTrema

Trema

Floodlight

POX

OpenFaucet

NOX 17

28

68

91

123

watcher数: 1位

12/6/2012 調べ12年12月9日日曜日

Page 83: SDN時代の開発よもやま話 - OpenFlowとTrema

Trema

NOX

POX

Beacon

Floodlight

OpenFaucet 0

3

4

5

16

29

サンプルApp数: 1位

01101101110101010111110101010111

12年12月9日日曜日

Page 84: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「どんな実アプリがあるの?」

12年12月9日日曜日

Page 85: SDN時代の開発よもやま話 - OpenFlowとTrema

Wakame-VDC

• コンパクトな Ruby 製 IaaS 基盤ソフト(e.g., OpenStack、Eucalyptus)

• 九州電力、NII など採用事例たくさん

• Rails による GUI

• ネットワークとストレージの仮想化

http://wakame.jp/document/15/

12年12月9日日曜日

Page 86: SDN時代の開発よもやま話 - OpenFlowとTrema

12年12月9日日曜日

Page 87: SDN時代の開発よもやま話 - OpenFlowとTrema

12年12月9日日曜日

Page 88: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「ネットワークカソウカ?」

12年12月9日日曜日

Page 89: SDN時代の開発よもやま話 - OpenFlowとTrema

12年12月9日日曜日

Page 90: SDN時代の開発よもやま話 - OpenFlowとTrema

ネットワークA

コントローラ

パッチパネル

転送

ネットワークB所属するネットワーク

をソフトウェアで切り替え12年12月9日日曜日

Page 91: SDN時代の開発よもやま話 - OpenFlowとTrema

「OpenFlowスイッチがないとダメ?」

12年12月9日日曜日

Page 92: SDN時代の開発よもやま話 - OpenFlowとTrema

既存のネットワーク

Wakame のエッジ仮想化

VM VM VM

物理ホスト

SWスイッチ

12年12月9日日曜日

Page 93: SDN時代の開発よもやま話 - OpenFlowとTrema

IP アドレスがかぶると?

VMVM

ユーザ X192.168.0.1 192.168.0.2

VMVM

ユーザ Y192.168.0.1 192.168.0.2

普通のスイッチ

→ユニキャストなら問題なし12年12月9日日曜日

Page 94: SDN時代の開発よもやま話 - OpenFlowとTrema

IP アドレスがかぶると?

VMVM

ユーザ X192.168.0.1 192.168.0.2

VMVM

ユーザ Y192.168.0.1 192.168.0.2

普通のスイッチ

→ブロードキャストで問題

192.168.0.2 のMACアドレスは?

はーい! はーい!

12年12月9日日曜日

Page 95: SDN時代の開発よもやま話 - OpenFlowとTrema

エッジスイッチでブロック

VMVM

ユーザ X192.168.0.1 192.168.0.2

VMVM

ユーザ Y192.168.0.1 192.168.0.2

エッジスイッチ192.168.0.2 の

MACアドレスは?

はーい!

12年12月9日日曜日

Page 96: SDN時代の開発よもやま話 - OpenFlowとTrema

エッジスイッチで書き換え

VMVM

ユーザ X ユーザ Y

ホストA

VMVM

ユーザ X ユーザ Y

ホストB

宛先をホストBへ

元に戻す

12年12月9日日曜日

Page 97: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「そろそろTremaでのプログラミング

を教えて!」

12年12月9日日曜日

Page 98: SDN時代の開発よもやま話 - OpenFlowとTrema

Tremaの特長

12年12月9日日曜日

Page 99: SDN時代の開発よもやま話 - OpenFlowとTrema

Tremaの特長

「今風」なフレームワーク

12年12月9日日曜日

Page 100: SDN時代の開発よもやま話 - OpenFlowとTrema

Tremaの特長

「今風」なフレームワーク

• Rubyによる簡潔な記述

12年12月9日日曜日

Page 101: SDN時代の開発よもやま話 - OpenFlowとTrema

Tremaの特長

「今風」なフレームワーク

• Rubyによる簡潔な記述

• フルスタック: ノートPC一台で開発

12年12月9日日曜日

Page 102: SDN時代の開発よもやま話 - OpenFlowとTrema

Tremaの特長

「今風」なフレームワーク

• Rubyによる簡潔な記述

• フルスタック: ノートPC一台で開発

• GitHub上でのオープンな開発 (GPL2)

12年12月9日日曜日

Page 103: SDN時代の開発よもやま話 - OpenFlowとTrema

(C) Miramax Films 2004

Tremaの哲学

一、短く書けて、一、すぐに動くべし

取間先生と れ ま

12年12月9日日曜日

Page 104: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「なぜ短く?」

12年12月9日日曜日

Page 105: SDN時代の開発よもやま話 - OpenFlowとTrema

短ければ短いほど、

•早くサッと作れて、•バグの発生率が小さく、•後々のメンテも楽だから

12年12月9日日曜日

Page 106: SDN時代の開発よもやま話 - OpenFlowとTrema

Trema でハブclass RepeaterHub < Controller def packet_in datapath_id, message send_flow_mod_add( datapath_id, :match => ExactMatch.from( message ), :actions => SendOutPort.new( OFPP_FLOOD ) ) send_packet_out( datapath_id, :packet_in => message, :actions => SendOutPort.new( OFPP_FLOOD ) ) endend

12年12月9日日曜日

Page 107: SDN時代の開発よもやま話 - OpenFlowとTrema

POX (Python)

12年12月9日日曜日

Page 108: SDN時代の開発よもやま話 - OpenFlowとTrema

POX (Python)from pox.core import coreimport pox.openflow.libopenflow_01 as of

class RepeaterHub (object): def __init__ (self, connection): self.connection = connection connection.addListeners(self)

def send_packet (self, buffer_id, raw_data, out_port, in_port): msg = of.ofp_packet_out() msg.in_port = in_port if buffer_id != -1 and buffer_id is not None: msg.buffer_id = buffer_id else: if raw_data is None: return msg.data = raw_data action = of.ofp_action_output(port = out_port) msg.actions.append(action) self.connection.send(msg)

def act_like_hub (self, packet, packet_in): self.send_packet(packet_in.buffer_id, packet_in.data, of.OFPP_FLOOD, packet_in.in_port)

def _handle_PacketIn (self, event): packet = event.parsed if not packet.parsed: return packet_in = event.ofp # The actual ofp_packet_in message. self.act_like_hub(packet, packet_in)

def launch (): def start_switch (event): RepeaterHub(event.connection) core.openflow.addListenerByName("ConnectionUp", start_switch)

12年12月9日日曜日

Page 109: SDN時代の開発よもやま話 - OpenFlowとTrema

NOX (C++)

12年12月9日日曜日

Page 110: SDN時代の開発よもやま話 - OpenFlowとTrema

NOX (C++)#include <boost/bind.hpp>#include <boost/shared_array.hpp>#include "assert.hh"#include "component.hh"#include "flow.hh"#include "packet-in.hh"

#include "vlog.hh"

#include "netinet++/ethernet.hh"

namespace {

using namespace vigil;using namespace vigil::container;

Vlog_module lg("hub");

class Hub : public Component {public: Hub(const Context* c, const json_object*) : Component(c) { }

void configure(const Configuration*) { }

Disposition handler(const Event& e) { const Packet_in_event& pi = assert_cast<const Packet_in_event&>(e);

uint32_t buffer_id = pi.buffer_id; Flow flow(pi.in_port, *(pi.get_buffer()));

if (flow.dl_type == ethernet::LLDP){ return CONTINUE; }

ofp_flow_mod* ofm; size_t size = sizeof *ofm + sizeof(ofp_action_output); boost::shared_array<char> raw_of(new char[size]); ofm = (ofp_flow_mod*) raw_of.get();

ofm->header.version = OFP_VERSION; ofm->header.type = OFPT_FLOW_MOD; ofm->header.length = htons(size); ofm->match.wildcards = htonl(0); ofm->match.in_port = htons(flow.in_port); ofm->match.dl_vlan = flow.dl_vlan; ofm->match.dl_vlan_pcp = flow.dl_vlan_pcp; memcpy(ofm->match.dl_src, flow.dl_src.octet, sizeof ofm->match.dl_src); memcpy(ofm->match.dl_dst, flow.dl_dst.octet, sizeof ofm->match.dl_dst); ofm->match.dl_type = flow.dl_type; ofm->match.nw_src = flow.nw_src; ofm->match.nw_dst = flow.nw_dst; ofm->match.nw_proto = flow.nw_proto;

ofm->match.tp_src = flow.tp_src; ofm->match.tp_dst = flow.tp_dst; ofm->cookie = htonl(0); ofm->command = htons(OFPFC_ADD); ofm->buffer_id = htonl(buffer_id); ofm->idle_timeout = htons(5); ofm->hard_timeout = htons(5); ofm->priority = htons(OFP_DEFAULT_PRIORITY); ofm->flags = htons(0); ofp_action_output& action = *((ofp_action_output*)ofm->actions); memset(&action, 0, sizeof(ofp_action_output)); action.type = htons(OFPAT_OUTPUT); action.len = htons(sizeof(ofp_action_output)); action.port = htons(OFPP_FLOOD); action.max_len = htons(0); send_openflow_command(pi.datapath_id, &ofm->header, true); free(ofm);

if (buffer_id == UINT32_MAX) { size_t data_len = pi.get_buffer()->size(); size_t total_len = pi.total_len; if (total_len == data_len) { send_openflow_packet(pi.datapath_id, *pi.get_buffer(), OFPP_FLOOD, pi.in_port, true); }

}

return CONTINUE; }

void install() { register_handler<Packet_in_event>(boost::bind(&Hub::handler, this, _1)); }};

REGISTER_COMPONENT(container::Simple_component_factory<Hub>, Hub);

}

12年12月9日日曜日

Page 111: SDN時代の開発よもやま話 - OpenFlowとTrema

Floodlight (Java)

12年12月9日日曜日

Page 112: SDN時代の開発よもやま話 - OpenFlowとTrema

Floodlight (Java)package net.floodlightcontroller.hub;

import java.io.IOException;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.Map;import net.floodlightcontroller.core.FloodlightContext;import net.floodlightcontroller.core.IFloodlightProviderService;

import net.floodlightcontroller.core.IOFMessageListener;import net.floodlightcontroller.core.IOFSwitch;import net.floodlightcontroller.core.module.FloodlightModuleContext;import net.floodlightcontroller.core.module.FloodlightModuleException;import net.floodlightcontroller.core.module.IFloodlightModule;import net.floodlightcontroller.core.module.IFloodlightService;import org.openflow.protocol.OFMessage;import org.openflow.protocol.OFPacketIn;import org.openflow.protocol.OFPacketOut;import org.openflow.protocol.OFPort;import org.openflow.protocol.OFType;import org.openflow.protocol.action.OFAction;import org.openflow.protocol.action.OFActionOutput;import org.openflow.util.U16;import org.slf4j.Logger;import org.slf4j.LoggerFactory;

public class Hub implements IFloodlightModule, IOFMessageListener { protected static Logger log = LoggerFactory.getLogger(Hub.class); protected IFloodlightProviderService floodlightProvider;

public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) { this.floodlightProvider = floodlightProvider; }

@Override public String getName() { return Hub.class.getPackage().getName(); }

public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { OFPacketIn pi = (OFPacketIn) msg; OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory() .getMessage(OFType.PACKET_OUT); po.setBufferId(pi.getBufferId()) .setInPort(pi.getInPort());

OFActionOutput action = new OFActionOutput() .setPort((short) OFPort.OFPP_FLOOD.getValue()); po.setActions(Collections.singletonList((OFAction)action));

po.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH);

if (pi.getBufferId() == 0xffffffff) { byte[] packetData = pi.getPacketData(); po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH + po.getActionsLength() + packetData.length)); po.setPacketData(packetData); } else { po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH + po.getActionsLength())); } try { sw.write(po, cntx); } catch (IOException e) { log.error("Failure writing PacketOut", e); }

return Command.CONTINUE; }

@Override public boolean isCallbackOrderingPrereq(OFType type, String name) { return false; }

@Override public boolean isCallbackOrderingPostreq(OFType type, String name) { return false; }

@Override public Collection<Class<? extends IFloodlightService>> getModuleServices() { return null; }

@Override public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { return null; }

@Override public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); l.add(IFloodlightProviderService.class); return l; }

@Override public void init(FloodlightModuleContext context) throws FloodlightModuleException { floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); }

@Override public void startUp(FloodlightModuleContext context) { floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);

}}

12年12月9日日曜日

Page 113: SDN時代の開発よもやま話 - OpenFlowとTrema

0

30

60

90

120

Trema (Ruby) POX (Python) NOX (C++) Floodlight (Java)

コード行数

14

36

95

111

12年12月9日日曜日

Page 114: SDN時代の開発よもやま話 - OpenFlowとTrema

フローテーブルの書き込みsend_flow_mod_add(

dpid, :match => ExactMatch.from( message ), :buffer_id => message.buffer_id, :actions => ActionOutput.new( message.in_port + 1 ))

inst.install_datapath_flow( dpid, extract_flow(packet), CACHE_TIMEOUT, openflow.OFP_FLOW_PERMANENT, [[openflow.OFPAT_OUTPUT, [0, prt[0]]]], bufid, openflow.OFP_DEFAULT_PRIORITY, inport, buf)

Trema

NOX

12年12月9日日曜日

Page 115: SDN時代の開発よもやま話 - OpenFlowとTrema

(C) Miramax Films 2004

Tremaの哲学

一、短く書けて、一、すぐに動くべし

取間先生と れ ま

12年12月9日日曜日

Page 116: SDN時代の開発よもやま話 - OpenFlowとTrema

SDN開発の面倒さ

プログラマの声

12年12月9日日曜日

Page 117: SDN時代の開発よもやま話 - OpenFlowとTrema

SDN開発の面倒さ"OpenFlow は開発環境の構築が面倒だ"

(ネットワーク設定や VM 構築とか)

プログラマの声

12年12月9日日曜日

Page 118: SDN時代の開発よもやま話 - OpenFlowとTrema

SDN開発の面倒さ"OpenFlow は開発環境の構築が面倒だ"

(ネットワーク設定や VM 構築とか)

"OpenFlow スイッチ持ってないよ"

プログラマの声

12年12月9日日曜日

Page 119: SDN時代の開発よもやま話 - OpenFlowとTrema

SDN開発の面倒さ"OpenFlow は開発環境の構築が面倒だ"

(ネットワーク設定や VM 構築とか)

"OpenFlow スイッチ持ってないよ"

"そもそも OpenFlow の実験ができる

ネットワーク持ってないし..."

プログラマの声

12年12月9日日曜日

Page 120: SDN時代の開発よもやま話 - OpenFlowとTrema

Tremaなら簡単!trema run コントローラ

起動

作成

12年12月9日日曜日

Page 121: SDN時代の開発よもやま話 - OpenFlowとTrema

Tremaなら簡単!trema run コントローラ

起動

作成

12年12月9日日曜日

Page 122: SDN時代の開発よもやま話 - OpenFlowとTrema

コントローラを書いてみよう

# simple-controller.rb

class SimpleController < Controller

end

% trema run simple-controller.rb

コンパイルなしですぐに実行

12年12月9日日曜日

Page 123: SDN時代の開発よもやま話 - OpenFlowとTrema

スイッチの起動を捕捉

class SimpleController < Controller

def switch_connected dpid

puts “Hello #{ dpid.to_hex }!”

end

end“スイッチ起動”イベントのハンドラを追加

12年12月9日日曜日

Page 124: SDN時代の開発よもやま話 - OpenFlowとTrema

仮想スイッチを接続# network.conf

vswitch { dpid 0xabc }

vswitch { dpid 0xdef }

% trema run simple-controller.rb \ -c network.conf

Hello 0xabc!Hello 0xdef!

12年12月9日日曜日

Page 125: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「パケットは 送れないの?」

12年12月9日日曜日

Page 126: SDN時代の開発よもやま話 - OpenFlowとTrema

パケットを送る# network.conf

vswitch { dpid 0xabc }

vswitch { dpid 0xdef }

vhost “host1”

vhost “host2”

link “0xabc”, “host1”

link “0xdef”, “host2”

12年12月9日日曜日

Page 127: SDN時代の開発よもやま話 - OpenFlowとTrema

パケットを送る

class SimpleController < Controller

def switch_connected dpid

puts “Hello #{ dpid.to_hex }!”

end

def packet_in dpid, message

puts “Unknown packet!”

end

end

12年12月9日日曜日

Page 128: SDN時代の開発よもやま話 - OpenFlowとTrema

パケットを送る

% trema send_packets --source host1 \ --dest host2 --n_pkts 10 --pps 10

Unknown packet!

Unknown packet!

Unknown packet!

Unknown packet!

Unknown packet!

...

12年12月9日日曜日

Page 129: SDN時代の開発よもやま話 - OpenFlowとTrema

SDNとはプログラミング分野の1つ

「GUIプログラミング」とかと同じ!

12年12月9日日曜日

Page 130: SDN時代の開発よもやま話 - OpenFlowとTrema

仮想ネットワークDSL

開発マシン上に好きなトポロジを構築して

コントローラを実行できる

•テストパケットを送受信してコントローラを

デバッグできる

•使える部品は仮想スイッチ、仮想ホスト、

仮想リンク

12年12月9日日曜日

Page 131: SDN時代の開発よもやま話 - OpenFlowとTrema

vswitch { dpid "0x1" }vswitch { dpid "0x2" }vswitch { dpid "0x3" }vswitch { dpid "0x4" } ...

link "0x1", "0x2"link "0x1", "0x3"link "0x1", "0x4"link "0x1", "0x5"link "0x1", "0x6"link "0x1", "0x7"link "0x1", "0x8"link "0x1", "0x9"link "0x1", "0x10"link "0x2", "0x3"link "0x2", "0x4" ...

スイッチ10台のフルメッシュ接続をベタ書き(約80行)

12年12月9日日曜日

Page 132: SDN時代の開発よもやま話 - OpenFlowとTrema

言語内 DSL$nswitch = 10

1.upto( $nswitch ).each do | sw1 | vswitch { dpid sw1.to_hex }

1.upto( $nswitch ).each do | sw2 | if sw1 < sw2 link sw1.to_hex, sw2.to_hex end endend

12年12月9日日曜日

Page 133: SDN時代の開発よもやま話 - OpenFlowとTrema

OpenFlow/SDN FAQ

「...GUIないの?」

12年12月9日日曜日

Page 134: SDN時代の開発よもやま話 - OpenFlowとTrema

Tremashark

12年12月9日日曜日

Page 135: SDN時代の開発よもやま話 - OpenFlowとTrema

12年12月9日日曜日

Page 136: SDN時代の開発よもやま話 - OpenFlowとTrema

SDNでTDD

12年12月9日日曜日

Page 137: SDN時代の開発よもやま話 - OpenFlowとTrema

SDNでTDD

•RSpecでネットワークをユニットテスト

12年12月9日日曜日

Page 138: SDN時代の開発よもやま話 - OpenFlowとTrema

SDNでTDD

•RSpecでネットワークをユニットテスト

•ホスト間でのパケットの送受信数

12年12月9日日曜日

Page 139: SDN時代の開発よもやま話 - OpenFlowとTrema

SDNでTDD

•RSpecでネットワークをユニットテスト

•ホスト間でのパケットの送受信数

•スイッチのフローテーブルの中身

12年12月9日日曜日

Page 140: SDN時代の開発よもやま話 - OpenFlowとTrema

SDNでTDD

•RSpecでネットワークをユニットテスト

•ホスト間でのパケットの送受信数

•スイッチのフローテーブルの中身

•Etc.

12年12月9日日曜日

Page 141: SDN時代の開発よもやま話 - OpenFlowとTrema

ハブのテストコードdescribe RepeaterHub do

around do | example | network { # ネットワークの定義 vswitch("switch") { datapath_id "0xabc" } vhost("host1") { promisc "on" } vhost("host2") { promisc "on" } link "switch", "host1" link "switch", "host2" }.run( RepeaterHub ) { example.run } end

context "when host1 sends one packet to host2" do describe "switch" do before { send_packets "host1", "host2" } subject { switch( "switch" ) } it { should have( 1 ).flows } its( "flows.first.actions" ) { should == "FLOOD" } end

...

仮想NWでハブを動かし、

フローテーブルの中身をテスト

12年12月9日日曜日

Page 142: SDN時代の開発よもやま話 - OpenFlowとTrema

まとめ

•SDNはプログラミング

•やってるとこはやっている(Google、Trema)

•Tremaで楽に作ろう

12年12月9日日曜日

Page 143: SDN時代の開発よもやま話 - OpenFlowとTrema

Amazon で好評予約中!

12年12月9日日曜日