diff --git a/CHANGELOG.md b/CHANGELOG.md index 6df407b6..c952b372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ # Changelog +## 0.2.0 (9/3/2015) +* [#30](https://github.com/yasuhito/trema-book/pull/30): 「OpenFlow の仕組み」章のドラフト rev.1 を追加. + ## 0.1.0 (8/31/2015) * Hello Trema 章のドラフト rev.1 を追加. diff --git a/Guardfile b/Guardfile index efc1d0e9..9bc793c5 100644 --- a/Guardfile +++ b/Guardfile @@ -1,4 +1,4 @@ -guard 'rake', task: :render do +guard 'rake', task: :html do watch(/.+\.adoc$/) end diff --git a/appendix.adoc b/appendix.adoc new file mode 100644 index 00000000..ab3e3fd1 --- /dev/null +++ b/appendix.adoc @@ -0,0 +1,5 @@ +[appendix] += Copyright and License +This book is released under the GNU General Public License version 3.0: + +- http://www.gnu.org/licenses/gpl-3.0.html diff --git a/book.adoc b/book.adoc index 648d17db..121784cd 100644 --- a/book.adoc +++ b/book.adoc @@ -1,13 +1,10 @@ = TremaでOpenFlowプログラミング 高宮 安仁 ; 鈴木 一哉; 松井 暢之; 村木 暢哉; 山崎 泰宏 -== OpenFlow って何? -// 仮置き +:leveloffset: 1 -include::hello_trema.adoc[leveloffset=+1] +include::how_does_openflow_work.adoc[] -[appendix] -== Copyright and License -This book is released under the GNU General Public License version 3.0: +include::hello_trema.adoc[] -- http://www.gnu.org/licenses/gpl-3.0.html +include::appendix.adoc[] diff --git a/how_does_openflow_work.adoc b/how_does_openflow_work.adoc new file mode 100644 index 00000000..4c8a7ada --- /dev/null +++ b/how_does_openflow_work.adoc @@ -0,0 +1,255 @@ += OpenFlowの仕組み +:imagesdir: images/how_does_openflow_work +:table-caption!: + +近ごろ話題のOpenFlowって、どんな仕組みで何がうれしいのでしょうか? 難しいネットワーク用語を使わずに、身近な話で解説します。 + +image::incredible_machine.png[] + +== ソフトウェアで思いどおりにコントロール + +[quote, Larry Wall, 『プログラミングPerl』(オーム社)] +無精 (Laziness): エネルギーの総支出を減らすために、多大な努力をするように、あなたをかりたてる性質。こうして労力を省くために書いたプログラムは他人も使うようになり、そのプログラムに関する質問にいちいち答えずに済ますためにドキュメントを書くようになる。それゆえ、プログラマにとって最も重要な素質である。またそれゆえ、この本が存在するのである。 + +優れたプログラマが持つハッカー気質の1つに「無精」があります。大好きなコンピュータの前から一時も離れずに、どうやってジャンクフードを手に入れるか……普通の人からするとただの横着に見えるかもしれませんが、ハッカー達にとってそれはいつでも大きな問題でした。 + +ソフトウェアによる横着はハッカーが最も創造性を発揮する分野の一つです。時間のかかる仕事も、うまく技術を駆使すれば自動化してさっと終わらせることができるのです。 + +1. ハッカーの巣窟として有名なMITのAIラボにはかつて、コンピュータからオンラインでピザを注文できるUNIXコマンドが存在しましたfootnote:[MITのxpizzaコマンドのマニュアル:https://stuff.mit.edu/afs/sipb/project/lnf/other/CONTRIB/ai-info]。ハックしていて腹が減ったらコマンドをたたいてピザを取る、なんとも横着です。 +2. コンピュータサイエンスの名門、カーネギーメロン大学にはコーク・マシンという変わったコーラ自販機がかつてあり、UNIXコマンド一発でコーラの冷え具合を確認できるようになっていましたfootnote:[カーネギーメロン大のコーク・マシンのサイト:http://www.cs.cmu.edu/~coke/]。遠くの自販機まで行って**ぬるい**コーラをつかまされないための工夫です。 +3. RFC (Request For Comment) で標準化されているコーヒーポットプロトコルでは、遠隔地にあるコーヒーポットのコーヒーの量を監視したり、コーヒーを自動的にいれたりするための半分冗談のインターフェースを定義していますfootnote:[RFC 2324:https://www.ietf.org/rfc/rfc2324.txt]。本当に実装してしまった人もいたそうですから驚きです。 + +こうした「ソフトウェアで楽をする」ハックのうち、もっとも大規模な例が最新鋭のデータセンターです。クラウドサービスの裏で動くデータセンターは極めて少人数のエンジニアが運用しており、大部分の管理作業をソフトウェアによって極限まで自動化している、という記事を呼んだことのある人も多いでしょう。このようにピザやコーラ、コーヒーのようなお遊びから、データセンターのように一筋縄ではいかない相手まで、ソフトウェアで「モノ」を思いどおりにコントロールするのは何よりも楽しく、そして実際に役立つハックの一種です。 + +[NOTE] +==== +こうした最新鋭データセンターでのネットワーク管理自動化の仕組みは第15章および第16章で解説します。 +==== + +== SDN: ネットワークをソフトウェアで制御しよう + +その中でもネットワークをハックする技術の1つが、本書で取り上げるOpenFlowです。簡単に言えば、OpenFlowとはネットワークスイッチの動作を制御するための標準プロトコルの1つです。OpenFlowを使えばスイッチ1つひとつの動作をソフトウェアから自由に書き換えられるので、究極的にはネットワーク全体の動作をソースコードとして記述できます。これをSoftware Defined Networking(SDN、ソフトウェアで定義されるネットワーク)と呼び、OpenFlowはSDNを実現する代表的な技術として注目を集めています。 + +OpenFlowの登場によって、これからはネットワークもプログラミングの対象になります。「いまだに手で管理してるの?そんなのソフトウェアで自動化しようぜ!」ハッカー達のこんな声が聞こえてきそうです。たしかに、今までネットワーク管理と言えば専門のオペレータ達による手作業がメインでした。横着できる部分はたくさんあるはずです。 + +ハッカーに負けない創造性とOpenFlowのプログラマブルな特性が組み合わされば、次のような「究極の自動化」も夢ではなくなります。 + +- 障害やトラフィック情報など、あらゆる情報を収集し集中管理できるネットワーク +- ユーザやアプリケーションの追加・削除に応じて、自動的に構成を変更するネットワーク +- 追加投資をしなくても、既存のインフラを目一杯まで使ってスケールするネットワーク + +本書はこれらすべてのトピックを扱います。自宅や職場のような中小規模ネットワークからデータセンターのような超大規模ネットワークまで、具体的なOpenFlowの適用例を見ながら「OpenFlowってどんなもので、具体的に何に使えるのだろう?」という素朴な疑問に答えます。また「さっそくOpenFlowを使ってすごいネットークを作ってみたい!」というプログラマ向けには、実際に動かせる実用的なコードをたくさん載せました。 + +本書を読み進めるにあたって、ネットワークやプログラミングの深い知識は不要です。基本から1つひとつ説明しますので、ネットワークの専門家はもちろん、プログラマやシステムエンジニア、そして営業職や管理職などなどOpenFlowに興味を持つ方であれば誰でもすんなり理解できるように構成してあります。ではさっそく、OpenFlowの仕組みを理解しましょう。 + +// TODO ネットワークの深い知識はいらないけどプログラミングは必要だ。 + +== OpenFlowの仕組み + +OpenFlowの仕組みを理解するために、ちょっとした**たとえ話**から始めましょう。みなさんもきっと利用したことがあると思いますが、よくあるカスタマーサポートを思い浮かべてください。そう、テレビとかパソコンの調子が悪くなったときに、フリーダイヤルで相談するアレです。それって、どこがOpenFlowと関係あるのでしょう? + +実はOpenFlowの基本的な仕組みはカスタマーサポートにとてもよく似ているのです。これからお話しするストーリーが分かれば、OpenFlowの95%を理解できたも同然です。それではさっそく、このストーリーの主人公の友太郎(ゆうたろう)君と、カスタマーサポートセンターで働く青井さん、そして上司の宮坂主任の3人に登場してもらいましょう。 + +=== エアコンが壊れた + +今年もエアコンの活躍する季節がやってきました。ところが友太郎君のエアコンはどうにも調子がよくありません。そこで取扱説明書に載っていたカスタマーサポートに電話することにしました。自動音声に従って問題ありそうな項目をすべてチェックしてみましたが、いっこうに解決しません。結局、自動音声はあきらめて電話サポートに相談することになりました。 + +「はい、こちらカスタマーサポートセンターです。担当はわたくし青井がうけたまわります。ご要件は何でしょうか?」 + +青井さんはヨーヨーダイン・エアコン社で働く電話オペレータです。お客さんから不具合の症状を聞き出し, 症状の内容に応じてそれぞれの担当サポートに電話をつなぎます(<>)。 + +[[yoyodyne_support]] +image::yoyodyne_support.png[caption="図1-1",title="電話サポートはお客さんからの問い合わせを適切な担当サポートへ転送"] + +「なんだかリモコンの調子が悪いんです。温度表示がずっと点滅してるんですけど、どうしたら直りますか?」 + +青井さんは手元の対応マニュアルを開きます (<>)。対応マニュアルには問い合わせ内容と、それを直せる担当サポートが載っています。続く数字はそれぞれの問い合わせ件数です。 + +[[operator_manual]] +.表1-1 電話サポート用対応マニュアル +|=== +| 問い合わせ内容 | 対応方法 | 問い合わせ件数 + +| リモコンの不調 | 周辺機器担当サポートに転送 | 8 件 +| エアコン本体の不調 | エアコン担当サポートに転送 | 6 件 +| 室外機の不調 | 周辺機器担当サポートに転送 | 4 件 +| いたずら電話 | 電話を切る | 2 件 +|=== + +ちょうどマニュアルの先頭に探していた項目がみつかりました。 + +「ご不便をおかけしました。担当のサポートにただいまおつなぎいたします」 + +電話の転送を終えると、青井さんはリモコン不調の問い合わせ件数を8件から9件にアップデートしました(<>)。 + +[[operator_manual_update]] +.表1-2 問い合わせ件数をアップデートする +|=== +| 問い合わせ内容 | 対応方法 | 問い合わせ件数 + +| リモコンの不調 | 周辺機器担当サポートに転送 | **9 件** +| エアコン本体の不調 | エアコン担当サポートに転送 | 6 件 +| 室外機の不調 | 周辺機器担当サポートに転送 | 4 件 +| いたずら電話 | 電話を切る | 2 件 +|=== + +こうすることでどんな問い合わせが多いかを社内にフィードバックできます。たとえばリモコンに関する問い合わせが多ければ、開発部署は次の製品開発にこの情報を生かしリモコンの改良をできますし、サポート部署は周辺機器担当のサポートメンバーを増やすという判断ができます。 + +=== これをOpenFlowに置き換えると… + +OpenFlowの世界では、パケットを送信するホストがお客さんの友太郎君、パケットを転送するOpenFlowスイッチが電話オペレータの青井さんに対応します(<>)。ホストがパケットを送ると、OpenFlowスイッチはパケットの中身に応じてパケットを適切に処理します。これはちょうど、青井さんが友太郎君からの問い合わせ内容に応じて適切な担当サポートに電話を転送するのと同じです。 + +[[openflow_host_switch]] +image::openflow_host_switch.png[caption="図1-2",title="OpenFlowではホストがお客さん、スイッチが電話サポートセンター、そしてフローテーブルがマニュアルに対応"] + +OpenFlowスイッチは、その動作が「マニュアル化」されています。カスタマーサポートの例では、青井さんはマニュアルから対応方法を調べました。OpenFlowスイッチは、パケットの処理方法をスイッチ内のフローテーブルと呼ぶデータベースを参照して決めます。青井さんの業務がすべマニュアル化されているのと同じく、OpenFlowスイッチの動作はすべてこのフローテーブルの中身によって決まります。 + +=== パケット処理内容を管理するフローテーブル + +フローテーブルには、「こういうパケットが届いたら、こう処理する」というルールがいくつか記録されています。このルールをフローエントリと呼びます。フローエントリはちょうど「リモコンの故障に関する問い合わせが来たら、リモコン担当サポートに電話を転送する」といったマニュアルの各項目に対応します。 + +実際のフローテーブルの例を見てみましょう。<>はあるスイッチのフローテーブルで、各行が1つひとつのフローエントリに対応します。フローエントリは主にマッチフィールド、インストラクション、そしてカウンタの3つの要素から成ります。 + +[[flow_table_entry]] +.表1-3 フローテーブルとフローエントリの例 +|=== +| マッチフィールド | インストラクション | カウンタ + +| 送信元IPアドレス = 192.168.1.00 | ポート8番に転送 | 80パケット +| VLAN ID = 10 | ポート10番に転送 | 64パケット +| 送信元MACアドレス = 00:50:56:c0:00:08 | VLAN ID = 2 を付けてポート8番に転送 | 24パケット +| 送信元IPアドレス = 27.55.0.0/16 | パケットを破棄 | 10 パケット +|=== + +- マッチフィールド:
マッチフィールドは届いたパケットに対応するフローエントリを探すための「条件」として使われます。たとえば「リモコンの調子がおかしい」という問い合わせから対応方法を決めたように、パケットの特徴に合うマッチフィールドから処理方法、つまりインストラクションを決めます。 +- インストラクション:
インストラクションは届いたパケットをどう処理するかという「処理方法」にあたります。たとえば「リモコン担当サポートへ引き継ぎ」と同じく、インストラクションには「スイッチのポート8番に転送」などと指定します。また転送だけでなく、パケットの書き換えや破棄もインストラクションで実行できます。 +- カウンタ:
カウンタはフローエントリごとのパケット処理量の記録です。たとえば「リモコン関連の問い合わせ数は9件」とマニュアルに記録したように、「このフローエントリに従って処理したパケットは80個」などといった情報が書き込まれます。 + +いかがでしょうか?カスタマーサポートとOpenFlowはよく似ていることがわかると思います。実はOpenFlowはとても単純で理解しやすい仕組みなのです。 + +=== エアコンがまたまた故障 + +エアコンもしばらくは順調でしたが、1ヶ月後また調子が悪くなってしまいました。友太郎君は再びカスタマーサポートへダイヤルします。 + +「エアコンの排水ホースがすぐ詰まっちゃうんです」 + +青井さんはいつものように手元の対応マニュアルを調べましたが、困ったことに排水ホースの項目は載っていません。どうやらまったく新しい不具合のようです。 + +「すみませんが少々お待ちください。対応可能なサポートがいるかどうか確認いたします」 + +そして電話口には録音された”しばらくお待ちください”のメッセージとどこか軽快な音楽が流れはじめました。 + +[[yoyodyne_support_miyasaka]] +image::yoyodyne_support_miyasaka.png[caption="図1-3",title="対応マニュアルに対処法が見つからなかった場合、上司に聞く"] + +こういう時、青井さんがいつも頼るのは上司の宮坂主任です(<>)。 + +「宮坂さん、排水ホースについての問い合わせが着てるのですが、どのサポート担当につなげばよいですか?」 + +「それだったら消耗品担当サポートだよ」 + +転送先がわかった青井さんは友太郎君の待つ電話に戻ります。 + +「大変お待たせいたしました。担当のサポートに転送いたします」 + +一度目の問い合わせと比べてかなり時間がかかってしまいましたが、これでようやく一件落着です。さらに青井さんは、宮坂主任から教わった消耗品担当サポートの連絡先をマニュアルに追加します (<>)。次からの同じ問い合わせにすばやく答えられるようにするためです。 + +[[operator_manual_add_row]] +.表1-4 マニュアルに新しい症状と転送先を追加してアップデートップデートする +|=== +| 故障の箇所 | 担当サポートの内線番号 | 問い合わせ件数 + +| リモコンの不調 | 周辺機器担当サポートに転送 | 9 件 +| エアコン本体の不調 | エアコン担当サポートに転送 | 6 件 +| 室外機の不調 | 周辺機器担当サポートに転送 | 4 件 +| いたずら電話 | 電話を切る | 2 件 +| **排水ホースの不調** | **消耗品担当サポートに転送** | **1 件** +|=== + +// 見出しで、コントローラが上司にあたるということをズバリ言ったほうがいいかも。 + +==== これをOpenFlowに置き換えると… + +OpenFlowでこの上司にあたるのがコントローラと呼ばれるソフトウェアです(<>)。OpenFlowでネットワークをプログラミングする場合、プログラマが書くのはこのコントローラの部分です。頭脳であるコントローラをソフトウェアとして記述することで、ネットワークを自由自在に制御できるというわけです。 + +[[openflow_host_switch_controller]] +image::openflow_host_switch_controller.png[caption="図1-4",title="フローテーブルにパケットのエントリーが見つからなかった場合、コントローラに問い合わせる"] + +フローテーブルに載っているパケットはスイッチが高速に転送してくれますが、フローテーブルに載っておらずスイッチ側でどう処理してよいかわかない予期せぬパケットが届くこともあります。この場合スイッチはこのパケットをコントローラに上げて「このパケットはどうすればよいですか?」と指示をあおぎます。コントローラはこのパケットの中身を調べ、どうすべきかという指示、つまり新しいフローエントリをフローテーブルに書き込んでやります。 + +このようにフローテーブルに載っていないパケットが届くと、コントローラへの問い合わせが発生するのでパケット転送がとても遅くなります。しかし、スイッチの起動時にコントローラが必要なフローエントリをあらかじめ書き込んでおくようにしておけば、スイッチ側だけで素早く処理できます。 + +[NOTE] +.コントローラへの問い合わせはどのくらい遅い? +==== +フローテーブルを使わずに、毎回コントローラが指示を出すとどうなるでしょうか? 結果は、何倍も遅くなります。試しに手元の環境で簡単なプログラムを書き、ソフトウェアスイッチで転送する場合とコントローラですべて処理する場合を比べてみたところ、性能に5倍もの差が出ました。もちろんこれはおおざっぱな値ですが、数倍は遅くなるという目安になります。また今回の実験はソフトウェアスイッチでしたが、ハードウェアスイッチを使うとこの差はさらに広がります。 + +// TODO 簡単なコードを書いて計測しなおす +// TODO packetoutで転送するのと、フローテーブルで転送するのを比較するというのはいい練習課題になるかも。 +==== + +== OpenFlowのうれしさ + +OpenFlowの仕組みの大枠は理解できたと思います。それでは最も肝心な部分、「OpenFlowって何がうれしいの?」を掘り下げてみましょう。 + +=== 自動化やシステム連携がしやすい + +カスタマーサポートセンターでは、あらかじめ適切なマニュアルを作っておけば業務はすべて電話サポートが自動的にやってくれます。これによって、全体の監督は管理職で実務は電話サポート、というふうにきっちりと分業できるようになります。たとえば電話サポートが実務をやってくれている間、管理職は他の部署との協業や調整に集中できます。 + +同様に、OpenFlowスイッチの制御はすべてソフトウェアであるコントローラで実現しているので、ネットワーク管理の自動化が用意です。さらにコントローラがRubyやPython、Javaなどよく知られた汎用言語で書いてあれば、既存のシステムやサービスなどとの連携も簡単です。たとえば、アプリケーションからの要求やビジネスポリシーの変更、問題発生などさまざまなトリガーに応じてネットワークの設定を変更するといった、一歩進んだ自動化もできます。 + +[NOTE] +==== +システム連携の一例として、コントローラとWebサーバ(Sinatra)を連携してコントローラにREST APIを実装する方法を第14章で解説します。また、実際のデータセンターでのコントローラと外部サービスの連携については第15章および16章で紹介します。 +==== + +=== ネットワークトラフィックを集中制御しやすい + +カスタマーサポートセンターでは問い合わせ件数の情報はすべて管理職に上がってくるため、混み具合の把握や全体の交通整理が楽です。もし特定のサポートに問い合わせが集中しても、問い合わせがうまくばらけるようにマニュアルを通じて電話サポートの全員に指示できます。反対にもし各サポートが個々に判断してしまうと、おなじサポートに問い合わせが偏ることは避けられません。 + +OpenFlowでもすべてのトラフィック情報はコントローラに上がってくるため、全体を見たトラフィックの最適化が可能です。各種カウンタを集計することで、コントローラはネットワーク全体のトラフィックデータを集められます。そしてその情報をもとに各スイッチのフローテーブルを更新することで、全体的に見て最適となるパケットの通り道を引けます。反対にもし個々のスイッチが判断してしまうと、うまくトラフィックを分散できません。 + +[NOTE] +==== +各種カウンタの収集方法については第4章で、またトラフィックの分散方法については第13章で解説します。 +==== + +=== ソフトウェア開発のテクニックやツールが使える + +コントローラはソフトウェアの一種なので、ソフトウェア開発で長年培われているさまざまなテクニックやツールをネットワーク構築に応用できます。 + +- 近年主流のアジャイル開発手法でコントローラを開発すれば、反復的な機能追加が可能。フィードバックを受けながら少しずつバージョンアップしてくことで、ネットワークを段階的に構築できる +- コントローラのユニットテストや受け入れテストを書くことで、ネットワーク全体を自動的にテストできる。テスト結果の出力は、そのまま仕様書の一部になる。ExcelやWordで書いた仕様書を別個に管理する必要はない +- コントローラのソースコードや関連データをgitなどのバージョン管理ツールで管理すれば、ネットワーク全体のバージョン管理やバージョン間の差分のチェック、および巻き戻しも可能 + +[NOTE] +==== +アジャイルやソフトウェアテストによるコントローラ開発手法については第7章で解説します。 +==== + +=== 負荷上昇に対してスケールしやすい + +従来のネットワーク専用機器をOpenFlowコントローラで置き換えれば、負荷上昇への対応がより柔軟になります。従来のファイアウォールやルータ、スイッチ、ロードバランサといった専用ネットワーク機器では、負荷が上がった際にはワンランク上のハイエンドな機器との置き換え、つまり垂直方向のアップグレードしか選択肢がありませんでした。しかし、専用機器をコントローラとしてソフトウェア実装できれば、汎用サーバ上にほぼ同様の機能を実装できることになります。そして、汎用サーバを増やすだけで、つまり水平方向に増設するだけで負荷上昇に対応できます。これを一般にNFV(Network Functions Virtualization)と呼びます。 + +[NOTE] +==== +従来のファイアウォールやルータ、スイッチといった専用機器は、ベンダが提供する機能をそのまま使うしかありませんでした。たとえば、100個ある機能のうち、本当に使いたい機能は10個だけだったとしても、100機能付きのルータを買うしかありません。これではある意味、フルコースしか頼めないフレンチレストランのようなものです。一部の機能しか利用していないのに障害ポイントが無数にあるので、切り分けやデバッグが難航することもままあります。 + +OpenFlowは回転ずしです。フランス料理の味に近づけるのは大変ですが、必要な機能だけをチョイスしてがんばって実装すれば、思い通りの機器が手に入るのです。 + +こうしたネットワーク機器のOpenFlow実装については、パッチパネルを第5章で、スイッチを第6章で、ファイアウォールを第9章で、ルータを第10, 11章でそれぞれ解説します。 +==== + +== OpenFlowで気をつけること + +もちろん、OpenFlowでもうれしいことばかりではありません。コントローラで制御を一手に引き受けるというモデルになっているため、スイッチの台数が増えたときのコントローラの負荷に気をつける必要があります。もし、フローテーブルに載っていないパケットが一気にコントローラへ到着すると、パケットの配送が遅延するか最悪の場合コントローラが停止してしまいます。 + +そこで、OpenFlowの使いどころやフローテーブルの残り容量にはとくに注意する必要があります。たとえばOpenFlowをインターネットのような多種多様のパケットが流れる環境につなげると、すぐにコントローラへの問い合わせが殺到しフローテーブルがいっぱいになって破綻してしまいます。しかしデータセンターなどの閉じた環境では、トラフィックの特徴や流れるパケットの種類はあらかじめ見当を付けておけます。そこで最低限のパケットのみがコントローラへ上がってくるようにうまくネットワークとフローエントリを設計することで、スイッチが増えてもスケールさせることができます。 + +// TODO このトピックをどの章で取り上げるかリンクを入れる + +== まとめ + +本章ではSDNを実現するための部品であるOpenFlowを解説しました。OpenFlowはフローテーブルを持つスイッチと、フローテーブルの内容を集中制御するソフトウェアであるコントローラから成ります。ネットワークの制御をソフトウェア化することによって、自動化やさざまななシステムとの連携、トラフィック制御のしやすさ、ソフトウェア技術の応用、ソフトウェアならではのスケーラビリティの高さ、などさまざまな恩恵があります。 + +では、さっそくOpenFlowプログラミングを始めてみましょう! diff --git a/images/how_does_openflow_work/incredible_machine.png b/images/how_does_openflow_work/incredible_machine.png new file mode 100644 index 00000000..2d8a1c2a Binary files /dev/null and b/images/how_does_openflow_work/incredible_machine.png differ diff --git a/images/how_does_openflow_work/openflow_host_switch.png b/images/how_does_openflow_work/openflow_host_switch.png new file mode 100644 index 00000000..3a8d1ac6 Binary files /dev/null and b/images/how_does_openflow_work/openflow_host_switch.png differ diff --git a/images/how_does_openflow_work/openflow_host_switch_controller.png b/images/how_does_openflow_work/openflow_host_switch_controller.png new file mode 100644 index 00000000..2beed02d Binary files /dev/null and b/images/how_does_openflow_work/openflow_host_switch_controller.png differ diff --git a/images/how_does_openflow_work/yoyodyne_support.png b/images/how_does_openflow_work/yoyodyne_support.png new file mode 100644 index 00000000..ad9859ee Binary files /dev/null and b/images/how_does_openflow_work/yoyodyne_support.png differ diff --git a/images/how_does_openflow_work/yoyodyne_support_miyasaka.png b/images/how_does_openflow_work/yoyodyne_support_miyasaka.png new file mode 100644 index 00000000..7419dea5 Binary files /dev/null and b/images/how_does_openflow_work/yoyodyne_support_miyasaka.png differ diff --git a/images/whats_openflow/incredible_machine.png b/images/whats_openflow/incredible_machine.png deleted file mode 100644 index b466322b..00000000 Binary files a/images/whats_openflow/incredible_machine.png and /dev/null differ diff --git a/images/whats_openflow/openflow_host_switch.png b/images/whats_openflow/openflow_host_switch.png deleted file mode 100644 index 41c84da9..00000000 Binary files a/images/whats_openflow/openflow_host_switch.png and /dev/null differ diff --git a/images/whats_openflow/openflow_host_switch_controller.png b/images/whats_openflow/openflow_host_switch_controller.png deleted file mode 100644 index 0f68c606..00000000 Binary files a/images/whats_openflow/openflow_host_switch_controller.png and /dev/null differ diff --git a/images/whats_openflow/yoyodyne_support.png b/images/whats_openflow/yoyodyne_support.png deleted file mode 100644 index 0eca6598..00000000 Binary files a/images/whats_openflow/yoyodyne_support.png and /dev/null differ diff --git a/images/whats_openflow/yoyodyne_support_miyasaka.png b/images/whats_openflow/yoyodyne_support_miyasaka.png deleted file mode 100644 index 581a33ed..00000000 Binary files a/images/whats_openflow/yoyodyne_support_miyasaka.png and /dev/null differ diff --git a/index.adoc b/index.adoc index 03a9f262..fa3a3a61 100644 --- a/index.adoc +++ b/index.adoc @@ -2,4 +2,8 @@ :leveloffset: 1 -include::book.adoc[] +include::how_does_openflow_work.adoc[] + +include::hello_trema.adoc[] + +include::appendix.adoc[] diff --git a/tasks/html.rake b/tasks/html.rake index bc51c448..42f18889 100644 --- a/tasks/html.rake +++ b/tasks/html.rake @@ -5,7 +5,7 @@ CLOBBER << 'index.html' task html: 'index.html' # rubocop:disable LineLength -file 'index.html' => ['index.adoc', 'hello_trema.adoc'] do |t| +file 'index.html' => ['index.adoc', 'how_does_openflow_work.adoc', 'hello_trema.adoc'] do |t| sh "bundle exec asciidoctor -a icons=font -a toc=left -a source-highlighter=coderay -d book index.adoc --out-file #{t.name}" end # rubocop:enable LineLength