それが僕には楽しかったんです。

ミドルウェアとかやってます

KLabの技術系インターンに参加してきた話

はじめに

人生初のインターンということでKLabさんの技術系インターンに参加してきました。
www.klab.com

今回、期間中お世話になったメンターは山本雅也さんです。
twitter.com


進捗払いに関してはどこのインターンに行った方も載せていますが、これに関しては割愛します。
詳しくは僕のツイッターを漁ってください。

インターンに行くまで

まず、何があったかというと昨年の9月頃にこんなことがありました。




はい、つまりはそういうことです。

この前に、chikuwait君と話していて
「ネットワーク、興味あるから勉強したいんだよねぇ」
と、雑に話した途端にこれです。

というわけで、この後に山本さんに直接連絡を取りリモートで面談を行い
すごくあっさりと決まってしまいました。

ただ、ネットワーク周りを本当にやったことがなかったのでインターンまでに
Linux カーネルモジュールで最速のEchoサーバを作る」

DHCPの仕様をざっくりと理解してくる」
といったことを事前に行いました。

進捗払いに関してはどこのインターンに行った方も載せていますが、これに関しては割愛します。
詳しくは僕のツイッターを漁ってください。

目標

今回のインターンでの目標はメンターである山本さんが作っているユーザ空間で動作するTCP/IPプロトコル・スタックである「microps」にDHCPクライアント機能を追加実装する。
ただ、それだけです。

micropsとは

micropsは前述の通り、ユーザ空間で動作するTCP/IPプロトコル・スタックで、Ethernetフレームの送受信を行います。
加えてカーネル内のプロトコル・スタックを使用していません。
僕が機能追加する前の段階でSocketライクなAPIを提供する機能もありました。

github.com

インターン(0日目)

飛行機代を抑えるために早朝の便をとり、なんと前日の昼前に東京着という意味不明なスケジュールで行動していました。
初の東京だったのでまずどこに行こうかと思い、やっぱりアキバにいってしまいました。
その後、紆余曲折を経てホテルに到着。初日からの戦闘に向けて美味しいものも食べてきました。

インターン(1日目)

この日は、10:30ごろにKLabさんが入っている六本木ヒルズ森タワーに行きました。
気合が入りすぎて5時ごろには起床していたので、何故か江東区から歩いていくという強行に出ました。

この日はまず
インターンのガイダンス説明から始まり
メンターさんの紹介やその他諸々の手続きを行い
その後すぐに会議室に移りmicropsの仕様とDHCPに関する説明を30分ほど受けました。

それからはひたすらに開発環境の構築やmicropsのビルドなどを行い、その日は終了。

インターン(2日目)

この日はDISCOVERパケットを構築すること、またそれを送信し返ってくるOFFERパケットを解析することが目標だった。
DHCPクライアントがどのようにIP等を手に入れているかというと、ざっくりと以下の4プロセスを踏む

  • DISCOVER パケットをクライアントがブロードキャストで送信
  • OFFER パケットが返ってくるので情報を解析
  • 必要な情報を取り出しREQUEST パケットに組み込み送信
  • ACK or NACKが返ってきて終了

2日目はこの前半2つを行った。

まずはRFCや事前資料からDISCOVERパケットを構築するところから始めた。
パケット自体は固定形式部分が234byte、可変形式のオプションが64byteという構成になっている。
またIPを取得していない状態でsocket等を使用するため、送受信は全てブロードキャストを使用する。
そのため、ブロードキャストフラグも使用し明示的にブロードキャストを指定。

オプションは4byteのマジックコードに始まり、パケットの種別を示すものが3byte続く。
その後はクライアントIDやMACアドレス、サーバ固有情報などが含まれ最終的には0xFFをStopperとしている。
Stopperから末尾まではデータが入っているはずがないので0x00で埋めてある。

ここまでがパケット構成となる。
その結果を以下に示す。

========== DHCP Message Debug Print ==========
    op: 1
 htype: 1
  hlen: 6
  hops: 0
   xid: 5abda168 (1522377064)
  secs: 0
 flags: 8000
ciaddr: 0.0.0.0
yiaddr: 0.0.0.0
siaddr: 0.0.0.0
giaddr: 0.0.0.0
chaddr: 08:00:27:0c:a1:27
 sname: 
  file: 
 magic: 63 53 82 63
option[35] 01
option[3d] 01 08 00 27 0c a1 27
option:[ff]
total 300 bytes (padding 47 bytes)

次に構築したパケットを送信、レスポンスを受信する処理を追加した。
ここで使用したものはmicropsに始めから搭載されていたudp関連のsocketライクなAPI

レスポンスデータは形式こそオプション以外では変化が無いもののオペコードは必ず2になって(送信時は1を指定)返ってくる。
またオプション部分でマジックコードの次もOFFERパケットを示すものに変わっている。

以下が受信したOFFERパケットの情報となる。

========== DHCP Message Debug Print ==========
    op: 2
 htype: 1
  hlen: 6
  hops: 0
   xid: 5abda168 (1522377064)
  secs: 0
 flags: 8000
ciaddr: 0.0.0.0
yiaddr: 192.168.0.102
siaddr: 192.168.0.1
giaddr: 0.0.0.0
chaddr: 08:00:27:0c:a1:27
 sname: 
  file: 
 magic: 63 53 82 63
option[35] 02
option[36] c0 a8 00 01
option[33] 00 00 02 58
option[01] ff ff ff 00
option[03] c0 a8 00 01
option[06] c0 a8 00 01
option[0f] 55 62 75 6e 74 75 53 65 72 76 65 72 44 48 43 50 53 65 72 76 65 72 2e 6c 6f 63 61 6c
option:[ff]
total 304 bytes (padding 0 bytes)

二日目はここで終了。

インターン(3日目)

3日目はOFFERパケットから必要な情報を取り出し、REQUESTパケットを構築し送信
返ってくるACK(or NACK)を解析して、micropsを使用したEchoサーバの設定に必要な情報を組み込むところまでが目標。

まずは、yiaddrから使えるIPを取り出してREQUESTパケットとして構築。
構築したパケット自体は2日目に行ったものとほとんど同様なので概要は省略。

========== DHCP Message Debug Print ==========
    op: 1
 htype: 1
  hlen: 6
  hops: 0
   xid: 5abda168 (1522377064)
  secs: 0
 flags: 8000
ciaddr: 0.0.0.0
yiaddr: 192.168.0.102
siaddr: 192.168.0.1
giaddr: 0.0.0.0
chaddr: 08:00:27:0c:a1:27
 sname: 
  file: 
 magic: 63 53 82 63
option[35] 03
option[3d] 01 08 00 27 0c a1 27
option[32] c0 a8 00 66
option:[ff]
total 300 bytes (padding 41 bytes)

次にACK(or NACK)を受け取る。
これもOFFERパケットの受信と同様に行った。

========== DHCP Message Debug Print ==========
    op: 2
 htype: 1
  hlen: 6
  hops: 0
   xid: 5abda168 (1522377064)
  secs: 0
 flags: 8000
ciaddr: 0.0.0.0
yiaddr: 192.168.0.102
siaddr: 192.168.0.1
giaddr: 0.0.0.0
chaddr: 08:00:27:0c:a1:27
 sname: 
  file: 
 magic: 63 53 82 63
option[35] 05
option[36] c0 a8 00 01
option[33] 00 00 02 58
option[01] ff ff ff 00
option[03] c0 a8 00 01
option[06] c0 a8 00 01
option[0f] 55 62 75 6e 74 75 53 65 72 76 65 72 44 48 43 50 53 65 72 76 65 72 2e 6c 6f 63 61 6c
option:[ff]
total 304 bytes (padding 0 bytes)

ここまでは前日に行っていたこととあまり大差なかったのですんなりいった。
問題はこのあと、実際にACKから必要なIPアドレスサブネットマスクデフォルトゲートウェイを取り出して設定として組み込む点だった。
IPアドレスなどはすぐに見つかり、RFCなどにオプション種別も記載されていたので比較的容易に発見できた。

それを組み込む際にip_init 関数が存在するがこいつを単に呼び出すとethernetフレームにipプロトコルが二重に追加されてしまう問題があった。
またルーティングテーブル周りの初期化や、このmicropsを利用する人が任意でDHCPクライアント機能を利用できるようにするなど
やることが山積みだった。

このあたりはメンターの山本さんの力を借りて(もちろんここまで来るのに絶大な支援があった)、実装することができた。

ここで3日目が終了。

インターン(4日目)

この日は、最低限の処理しか追加していなかったコードにオプション解析などを組み込みデータがちゃんと正しいものか、こちらが想定しているものかチェックする処理などを追加
その後はひたすら鬼のペアプロコードリファクタリングを行った。(多分これが一番きつかった)

インターン(5日目)

この日は最終成果発表に向けて資料の準備とPRの作成を行った。
期間中、多大なご迷惑をお掛けした分プルリクがマージされた時はすごく嬉しかったというか、やったぞという気持ちしかなかった。

その後の成果発表も無事に終わり、Klabの方々とご飯を食べに行きこの日は終了。
そしてインターンも終了。

インターン(6日目)

帰りの飛行機は例によって飛行機代を抑えるためにほぼ最終便をとっていた。
そのため、馬鹿みたいに時間があったので大門->スカイツリー->浅草->上野、アキバと観光してきた。
余談ではあるが、人生経験の一環としてメイドカフェに行こうか本気で迷った。

さいごに

というわけで長かったようで短く感じた怒涛の初インターンは終了した。
インターンでやったことあったことを雑にまとめてみたが、実際にはスケジュールがかつかつで8時間はコードを書いている日の連続だった。
技術的な面でも未熟であったことがわかったが、その他にも色々と自分には知らないことが多かった。
成果発表で、色々なエンジニアの方に今回何をやったかということを報告し「わからない事にわからないなりに挑戦し、完成させたという点は評価できる」との評価を頂いたが
やはり実際に作っている時などに、「これはきいたことがあるぞ」「これは知っているかもしれない」と思っていたこともあったがそれをいざ実行しようとなると「お、なんか上手くいかないぞ」といったことが多くあり
わかっている事とできる事は全く別物であると痛感した。
また、自分は今までコードばかりを書いていてそれが楽しかったからというのもあるが
もっと自分が作るものの基盤的な知識を身につけなければいけないということも実感した。

そういった、自身の弱点のようなものを見続けたので今回のインターンはすごく辛く感じる面が多かった。

しかし、それ以上にものすごいレベルのエンジニアの方たちに囲まれて
今回のようにコードを書いて、何かを実現してという環境に身を置けたのはすごく楽しかった。
辛いと感じることもあったが、それでもわからないことをわからないと認めてその上で色々と試行錯誤を繰り返し一つの問題を解決していく。そういった時間を過ごせたことはこの上なく幸せな時間だった。

学ぶべきことが多く分かった反面で、学んだことも非常に多かった。
一週間ではあったが自分自身が以前に比べて成長できたことを感じることができたのでインターンに参加して本当によかったと思った。


最後に、今自分がいる大学ではあまり情報系に熱心な同期がいない。
そして家でもコードを書いて、それを楽しいと5年も言い続けている自分はそんな普通な人からみるとキモいという対象らしい。
そんな人たちに流されて普通の大学生活を送ろうとしていたが、今回のインターンでお昼休みなどに山本さんとキャリアについて話していて
自分のやりたいことがはっきりと見えたので周りを気にしないで残りの学生生活を自分なりに有効活用しようと思う。

本当に今回インターンに参加できてよかったとおもう。
今回、お世話になったKLabの皆さん、そしてなによりメンターとして1週間指導してくださった山本雅也さん
本当にありがとうございました。

無限インターン行きたい!!