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

15,087 views

Published on

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

Published in: Technology
0 Comments
40 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
15,087
On SlideShare
0
From Embeds
0
Number of Embeds
807
Actions
Shares
0
Downloads
237
Comments
0
Likes
40
Embeds 0
No embeds

No notes for slide

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

  1. 1. ∼SDN時代の開発よもやま話∼ OpenFlowとTrema 高宮安仁 (Trema開発チーム)12年12月9日日曜日
  2. 2. FAQ よくある疑問12年12月9日日曜日
  3. 3. OpenFlow/SDN FAQ 「何の役に立つの?」12年12月9日日曜日
  4. 4. 世界で初めて、 OpenFlow/SDN 開発を扱った本 2013/1/8 発売12年12月9日日曜日
  5. 5. SDN とは12年12月9日日曜日
  6. 6. SDN とは プログラミング分野の1つ12年12月9日日曜日
  7. 7. SDN プログラミング分野の1つ とは 「GUIプログラミング」 とかと同じ!12年12月9日日曜日
  8. 8. OpenFlow とは12年12月9日日曜日
  9. 9. OpenFlow とは SDNのいち実装方式12年12月9日日曜日
  10. 10. OpenFlow とは SDNのいち実装方式 GtkとかCocoa とかと同じ!12年12月9日日曜日
  11. 11. SDN つまり OpenFlow12年12月9日日曜日
  12. 12. SDN つまり OpenFlow は純粋にソフトウェア開発の話。12年12月9日日曜日
  13. 13. MAKE 「評論もいーけど、動いて役に 立つもの作りません?」12年12月9日日曜日
  14. 14. すでにバックボーンは OpenFlowで作っちゃた Urs Hölzle http://itpro.nikkeibp.co.jp/article/NEWS/20120418/391401/12年12月9日日曜日
  15. 15. OpenFlow/SDN FAQ 「何の役に立つの?」 →Googleの事例を解説12年12月9日日曜日
  16. 16. Googleのチャレンジ 最先 • 平均 PUE = 1.13 端 • 年間アベイラビリティ = 99.984% • 処理するデータ量/day = 数十ペタ12年12月9日日曜日
  17. 17. Googleのチャレンジ 最先 • 平均 PUE = 1.13 端 • 年間アベイラビリティ = 99.984% • 処理するデータ量/day = 数十ペタ 次の チャレンジは データセンター をつなぐネッ トワークだ!12年12月9日日曜日
  18. 18. WAN 回線のコスト 日米間(4.8Tbps、1万km)=320億円12年12月9日日曜日
  19. 19. WAN 回線のコスト 日米間(4.8Tbps、1万km)=320億円 回線を 追加せずに、 既存のを有 効活用したい12年12月9日日曜日
  20. 20. DC どれだけ流せる? DC DC12年12月9日日曜日
  21. 21. 従来のルーティング • ルータは自律分散で動く • 宛先に対して必ず最短路を選択 • 帯域の使用量は加味してくれない12年12月9日日曜日
  22. 22. DC 集中 DC ヒマ? DC12年12月9日日曜日
  23. 23. DC 理想 DC DC12年12月9日日曜日
  24. 24. 帯域は? DC DC 10Gbps 6Gbps DC12年12月9日日曜日
  25. 25. DC DC 10Gbps ? 6Gbps DC12年12月9日日曜日
  26. 26. DC DC どう分ける? DC12年12月9日日曜日
  27. 27. TEサーバ DC DC DC12年12月9日日曜日
  28. 28. TEサーバ DC 空き帯域 DC の収集 DC12年12月9日日曜日
  29. 29. TEサーバ DC 空き帯域 DC 帯域の の収集 割り当て DC12年12月9日日曜日
  30. 30. TEサーバ DC DC DC12年12月9日日曜日
  31. 31. TEサーバ DC DC DC12年12月9日日曜日
  32. 32. TEサーバ DC BGPルータ BGP処理部 コントローラ OpenFlow12年12月9日日曜日 スイッチ
  33. 33. TEサーバ DC BGPルータ BGP処理部 経路情報 コントローラ OpenFlow12年12月9日日曜日 スイッチ
  34. 34. TEサーバ DC BGPルータ BGP処理部 経路情報 コントローラ トラフィック 情報 OpenFlow12年12月9日日曜日 スイッチ
  35. 35. TEサーバ DC BGPルータ BGP処理部 経路情報 コントローラ トラフィック 情報 OpenFlow12年12月9日日曜日 スイッチ
  36. 36. TEサーバ 経路制御 DC BGPルータ BGP処理部 経路情報 コントローラ トラフィック 情報 OpenFlow12年12月9日日曜日 スイッチ
  37. 37. TEサーバ 経路制御 DC BGPルータ BGP処理部 経路情報 コントローラ トラフィック 情報 OpenFlow12年12月9日日曜日 スイッチ
  38. 38. Google WANの利用率 ほぼ100% 使い切り12年12月9日日曜日
  39. 39. TEサーバ DC BGPルータ BGP処理部 コントローラ OpenFlow12年12月9日日曜日 スイッチ
  40. 40. OpenFlow/SDN FAQ 「どういう仕組み?」12年12月9日日曜日
  41. 41. 2分で分かる OpenFlow12年12月9日日曜日
  42. 42. 従来のスイッチ 制御する パケットの ソフトウェア 転送ルール ファーム フロー ウェア領域 テーブル12年12月9日日曜日
  43. 43. ソフトウェア コントローラ OpenFlow プロトコル フロー テーブル ハードウェア12年12月9日日曜日
  44. 44. コントローラ フロー テーブル 転送ルール を参照 速い12年12月9日日曜日
  45. 45. コントローラ 知らない パケット フロー テーブル 転送ルール を参照 速い12年12月9日日曜日
  46. 46. コントローラ フローテーブル の更新 知らない パケット フロー テーブル 転送ルール を参照 速い12年12月9日日曜日
  47. 47. コントローラ フローテーブル 遅い の更新 知らない パケット フロー テーブル 転送ルール を参照 速い12年12月9日日曜日
  48. 48. OpenFlow/SDN FAQ 「何がうれしいの?」12年12月9日日曜日
  49. 49. OpenFlowのうれしさ12年12月9日日曜日
  50. 50. OpenFlowのうれしさ • ソフトウェアによる高い自由度12年12月9日日曜日
  51. 51. OpenFlowのうれしさ • ソフトウェアによる高い自由度 • システム連携と自動化12年12月9日日曜日
  52. 52. OpenFlowのうれしさ • ソフトウェアによる高い自由度 • システム連携と自動化 • ソフトウェア開発手法をネットワーク に適用できる12年12月9日日曜日
  53. 53. コントローラ 好きな言語で書ける OpenFlow Ruby, Python, C++,Java,... プロトコル フロー テーブル 既存のプロトコルに 縛られない (e.g.,VLANの上限)12年12月9日日曜日
  54. 54. TEサーバ ミドル DB コントローラ 自由に連携 フロー テーブル12年12月9日日曜日
  55. 55. データセンター GFS Paxos Chubby12年12月9日日曜日
  56. 56. データセンター GFS Paxos コントローラ Chubby フロー テーブル12年12月9日日曜日
  57. 57. データセンター GFS Paxos コントローラ Chubby フロー テーブル12年12月9日日曜日
  58. 58. ソフトウェア手法の応用12年12月9日日曜日
  59. 59. ソフトウェア手法の応用 • ネットワークを段階的に反復構築 (アジャイル)12年12月9日日曜日
  60. 60. ソフトウェア手法の応用 • ネットワークを段階的に反復構築 (アジャイル) • ネットワークのテスト (各種テスト、テストドリブン)12年12月9日日曜日
  61. 61. ソフトウェア手法の応用 • ネットワークを段階的に反復構築 (アジャイル) • ネットワークのテスト (各種テスト、テストドリブン) • バージョン管理や巻き戻し (git などのバージョン管理ツール)12年12月9日日曜日
  62. 62. OpenFlow/SDN FAQ 「フローテーブルで 何ができるの?」12年12月9日日曜日
  63. 63. 12年12月9日日曜日
  64. 64. スイッチ コントローラ パケットの宛先 MACアドレス →出力ポート 転送12年12月9日日曜日
  65. 65. スイッチ(トラフィックモニタ) コントローラ トラフィック 情報 流量 転送12年12月9日日曜日
  66. 66. ルータ コントローラ 書き換え 転送 送信元・宛先 MACアドレスを 書き換え12年12月9日日曜日
  67. 67. 12年12月9日日曜日
  68. 68. ロードバランサ バックエンド コントローラ サーバ トラフィック 情報 流量 書き換え 転送 トラフィック量に 応じて転送先を調整12年12月9日日曜日
  69. 69. 帯域を目一杯使う DC DC 転送 転送 転送 転送 転送 転送12年12月9日日曜日
  70. 70. レプリケーション DC 分岐 DC DC 分岐 DC 分岐 DC12年12月9日日曜日
  71. 71. パッチパネル コントローラ ネットワーク A 転送 ネットワーク 所属するネットワーク B をソフトウェアで切り替え12年12月9日日曜日
  72. 72. パッチパネル コントローラ ネットワーク A 転送 ネットワーク 所属するネットワーク B をソフトウェアで切り替え12年12月9日日曜日
  73. 73. パッチパネル コントローラ ネットワーク A 転送 ネットワーク 所属するネットワーク B をソフトウェアで切り替え12年12月9日日曜日
  74. 74. OpenFlow/SDN FAQ 「どう作るの?」12年12月9日日曜日
  75. 75. 主なOpenFlow プログラミングフレームワーク •Trema (Ruby) • POX (Python) • NOX (C++) • Floodlight (Java)12年12月9日日曜日
  76. 76. バージョン対応状況12年12月9日日曜日
  77. 77. バージョン対応状況 1.0 1.1 1.2 1.312年12月9日日曜日
  78. 78. バージョン対応状況 Trema POX NOX Floodlight 1.0 1.1 1.2 1.312年12月9日日曜日
  79. 79. バージョン対応状況 Trema POX NOX Floodlight TremaEdge 1.0 1.1 1.2 1.312年12月9日日曜日
  80. 80. 12年12月9日日曜日
  81. 81. 12年12月9日日曜日
  82. 82. watcher数: 1位 Trema 123 Floodlight 91 POX 68 OpenFaucet 28 NOX 17 12/6/2012 調べ12年12月9日日曜日
  83. 83. サンプルApp数: 1位 Trema 29 NOX 16 POX 5 01101101 Beacon 4 11010101 Floodlight 3 01111101 OpenFaucet 0 0101011112年12月9日日曜日
  84. 84. OpenFlow/SDN FAQ 「どんな実アプリが あるの?」12年12月9日日曜日
  85. 85. Wakame-VDC http://wakame.jp/document/15/ • コンパクトな Ruby 製 IaaS 基盤ソフト (e.g., OpenStack、Eucalyptus) • 九州電力、NII など採用事例たくさん • Rails による GUI • ネットワークとストレージの仮想化12年12月9日日曜日
  86. 86. 12年12月9日日曜日
  87. 87. 12年12月9日日曜日
  88. 88. OpenFlow/SDN FAQ 「ネットワーク カソウカ?」12年12月9日日曜日
  89. 89. 12年12月9日日曜日
  90. 90. パッチパネル コントローラ ネットワーク A 転送 ネットワーク 所属するネットワーク B をソフトウェアで切り替え12年12月9日日曜日
  91. 91. 「OpenFlowスイッチ がないとダメ?」12年12月9日日曜日
  92. 92. Wakame のエッジ仮想化 VM VM VM SW スイッチ 物理ホスト 既存の ネットワーク12年12月9日日曜日
  93. 93. IP アドレスがかぶると? ユーザ X ユーザ Y 192.168.0.1 192.168.0.2 192.168.0.1 192.168.0.2 VM VM VM VM 普通のスイッチ →ユニキャストなら問題なし12年12月9日日曜日
  94. 94. IP アドレスがかぶると? ユーザ X ユーザ Y はーい! 192.168.0.2 はーい! 192.168.0.1 192.168.0.1 192.168.0.2 VM VM VM VM 192.168.0.2 のMACアドレスは? 普通のスイッチ →ブロードキャストで問題12年12月9日日曜日
  95. 95. エッジスイッチでブロック ユーザ X ユーザ Y 192.168.0.1 はーい! 192.168.0.2 192.168.0.1 192.168.0.2 VM VM VM VM 192.168.0.2 の MACアドレスは? エッジスイッチ12年12月9日日曜日
  96. 96. エッジスイッチで書き換え ホストA ホストB ユーザ X ユーザ Y ユーザ X ユーザ Y VM VM VM VM 宛先を 元に戻す ホストBへ12年12月9日日曜日
  97. 97. OpenFlow/SDN FAQ 「そろそろTrema でのプログラミング を教えて!」12年12月9日日曜日
  98. 98. Tremaの特長12年12月9日日曜日
  99. 99. Tremaの特長 「今風」なフレームワーク12年12月9日日曜日
  100. 100. Tremaの特長 「今風」なフレームワーク • Rubyによる簡潔な記述12年12月9日日曜日
  101. 101. Tremaの特長 「今風」なフレームワーク • Rubyによる簡潔な記述 • フルスタック: ノートPC一台で開発12年12月9日日曜日
  102. 102. Tremaの特長 「今風」なフレームワーク • Rubyによる簡潔な記述 • フルスタック: ノートPC一台で開発 • GitHub上でのオープンな開発 (GPL2)12年12月9日日曜日
  103. 103. Tremaの哲学 一、短く書けて、 一、すぐに動くべし と れ ま 取間先生 (C) Miramax Films 200412年12月9日日曜日
  104. 104. OpenFlow/SDN FAQ 「なぜ短く?」12年12月9日日曜日
  105. 105. 短ければ短いほど、 • 早くサッと作れて、 • バグの発生率が小さく、 • 後々のメンテも楽だから12年12月9日日曜日
  106. 106. 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 ) ) end end12年12月9日日曜日
  107. 107. POX (Python)12年12月9日日曜日
  108. 108. POX (Python) from pox.core import core import 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日日曜日
  109. 109. NOX (C++)12年12月9日日曜日
  110. 110. 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日日曜日
  111. 111. Floodlight (Java)12年12月9日日曜日
  112. 112. 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日日曜日
  113. 113. コード行数 120 111 95 90 60 36 30 14 0 Trema (Ruby) POX (Python) NOX (C++) Floodlight (Java)12年12月9日日曜日
  114. 114. フローテーブルの書き込み send_flow_mod_add( Trem dpid, :match => ExactMatch.from( message ), a :buffer_id => message.buffer_id, :actions => ActionOutput.new( message.in_port + 1 ) ) NOX 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 )12年12月9日日曜日
  115. 115. Tremaの哲学 一、短く書けて、 一、すぐに動くべし と れ ま 取間先生 (C) Miramax Films 200412年12月9日日曜日
  116. 116. SDN開発の面倒さ プログラマの声12年12月9日日曜日
  117. 117. SDN開発の面倒さ "OpenFlow は開発環境の構築が面倒だ" (ネットワーク設定や VM 構築とか) プログラマの声12年12月9日日曜日
  118. 118. SDN開発の面倒さ "OpenFlow は開発環境の構築が面倒だ" (ネットワーク設定や VM 構築とか) "OpenFlow スイッチ持ってないよ" プログラマの声12年12月9日日曜日
  119. 119. SDN開発の面倒さ "OpenFlow は開発環境の構築が面倒だ" (ネットワーク設定や VM 構築とか) "OpenFlow スイッチ持ってないよ" "そもそも OpenFlow の実験ができる ネットワーク持ってないし..." プログラマの声12年12月9日日曜日
  120. 120. Tremaなら簡単! trema run コントローラ 起動 作成12年12月9日日曜日
  121. 121. Tremaなら簡単! trema run コントローラ 起動 作成12年12月9日日曜日
  122. 122. コントローラを書いてみよう # simple-controller.rb class SimpleController < Controller end コンパイルなしですぐに実行 % trema run simple-controller.rb12年12月9日日曜日
  123. 123. スイッチの起動を捕捉 class SimpleController < Controller def switch_connected dpid puts “Hello #{ dpid.to_hex }!” end end “スイッチ起動”イベントの ハンドラを追加12年12月9日日曜日
  124. 124. 仮想スイッチを接続 # network.conf vswitch { dpid 0xabc } vswitch { dpid 0xdef } % trema run simple-controller.rb -c network.conf Hello 0xabc! Hello 0xdef!12年12月9日日曜日
  125. 125. OpenFlow/SDN FAQ 「パケットは 送れないの?」12年12月9日日曜日
  126. 126. パケットを送る # network.conf vswitch { dpid 0xabc } vswitch { dpid 0xdef } vhost “host1” vhost “host2” link “0xabc”, “host1” link “0xdef”, “host2”12年12月9日日曜日
  127. 127. パケットを送る class SimpleController < Controller def switch_connected dpid puts “Hello #{ dpid.to_hex }!” end def packet_in dpid, message puts “Unknown packet!” end end12年12月9日日曜日
  128. 128. パケットを送る % 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日日曜日
  129. 129. SDN プログラミング分野の1つ とは 「GUIプログラミング」 とかと同じ!12年12月9日日曜日
  130. 130. 仮想ネットワークDSL 開発マシン上に好きなトポロジを構築して コントローラを実行できる • テストパケットを送受信してコントローラを デバッグできる • 使える部品は仮想スイッチ、仮想ホスト、 仮想リンク12年12月9日日曜日
  131. 131. スイッチ10台のフルメッシュ接続を ベタ書き(約80行) 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" ...12年12月9日日曜日
  132. 132. 言語内 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 end end12年12月9日日曜日
  133. 133. OpenFlow/SDN FAQ 「...GUIないの?」12年12月9日日曜日
  134. 134. Tremashark12年12月9日日曜日
  135. 135. 12年12月9日日曜日
  136. 136. SDNでTDD12年12月9日日曜日
  137. 137. SDNでTDD • RSpecでネットワークを ユニットテスト12年12月9日日曜日
  138. 138. SDNでTDD • RSpecでネットワークを ユニットテスト • ホスト間でのパケットの送受信数12年12月9日日曜日
  139. 139. SDNでTDD • RSpecでネットワークを ユニットテスト • ホスト間でのパケットの送受信数 • スイッチのフローテーブルの中身12年12月9日日曜日
  140. 140. SDNでTDD • RSpecでネットワークを ユニットテスト • ホスト間でのパケットの送受信数 • スイッチのフローテーブルの中身 • Etc.12年12月9日日曜日
  141. 141. ハブのテストコード describe RepeaterHub do around do | example | network { # ネットワークの定義 vswitch("switch") { datapath_id "0xabc" } vhost("host1") { promisc "on" } 仮想NWで 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 ...12年12月9日日曜日
  142. 142. まとめ • SDNはプログラミング •やってるとこはやっている (Google、Trema) • Tremaで楽に作ろう12年12月9日日曜日
  143. 143. Amazon で 好評予約中!12年12月9日日曜日

×