@@ -33,10 +33,17 @@ type ipHeader struct {
33
33
destAddr uint32 // 送信先IPアドレス
34
34
}
35
35
36
+ type ipRouteType uint8
37
+
38
+ const (
39
+ connected ipRouteType = iota
40
+ network
41
+ )
42
+
36
43
type ipRouteEntry struct {
37
- ipRouteType bool
38
- netdev * netDevice
39
- nexthop uint32
44
+ iptype ipRouteType
45
+ netdev * netDevice
46
+ nexthop uint32
40
47
}
41
48
42
49
func (ipheader ipHeader ) ToPacket () (ipHeaderByte []byte ) {
@@ -173,11 +180,70 @@ func ipInputToOurs(inputdev *netDevice, ipheader ipHeader, packet []byte) {
173
180
}
174
181
}
175
182
183
+ /*
184
+ IPパケットを直接イーサネットでホストに送信
185
+ */
186
+ func ipPacketOutputToHost (dev * netDevice , destAddr uint32 , packet []byte ) {
187
+ // ARPテーブルの検索
188
+ destMacAddr := searchArpTableEntry (destAddr )
189
+ if destMacAddr == [6 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 } {
190
+ // ARPエントリが無かったら
191
+ fmt .Printf ("Trying ip output to host, but no arp record to %s\\ n" , printIPAddr (destAddr ))
192
+ // ARPリクエストを送信
193
+ sendArpRequest (dev , destAddr )
194
+ } else {
195
+ // ARPエントリがあり、MACアドレスが得られたらイーサネットでカプセル化して送信
196
+ ethernetOutput (dev , destMacAddr , packet , ETHER_TYPE_IP )
197
+ }
198
+ }
199
+
200
+ /*
201
+ IPパケットをNextHopに送信
202
+ */
203
+ func ipPacketOutputToNetxhop (dev * netDevice , nextHop uint32 , packet []byte ) {
204
+ // ARPテーブルの検索
205
+ destMacAddr := searchArpTableEntry (nextHop )
206
+ if destMacAddr == [6 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 } {
207
+ fmt .Printf ("Trying ip output to next hop, but no arp record to %s\n " , printIPAddr (nextHop ))
208
+ // ルーティングテーブルのルックアップ
209
+ routeToNexthop := iproute .radixTreeSearch (nextHop )
210
+ if routeToNexthop == (ipRouteEntry {}) || routeToNexthop .iptype != connected {
211
+ // next hopへの到達性が無かったら
212
+ fmt .Printf ("Next hop %s is not reachable\n " , printIPAddr (nextHop ))
213
+ } else {
214
+ // ARPリクエストを送信
215
+ sendArpRequest (routeToNexthop .netdev , nextHop )
216
+ }
217
+ } else {
218
+ // ARPエントリがあり、MACアドレスが得られたらイーサネットでカプセル化して送信
219
+ ethernetOutput (dev , destMacAddr , packet , ETHER_TYPE_IP )
220
+ }
221
+ }
222
+
223
+ /*
224
+ IPパケットを送信
225
+ */
226
+ func ipPacketOutput (outputdev * netDevice , routeTree radixTreeNode , destAddr , srcAddr uint32 , packet []byte ) {
227
+ // 宛先IPアドレスへの経路を検索
228
+ route := routeTree .radixTreeSearch (destAddr )
229
+ if route == (ipRouteEntry {}) {
230
+ // 経路が見つからなかったら
231
+ fmt .Printf ("No route to %s\n " , printIPAddr (destAddr ))
232
+ }
233
+ if route .iptype == connected {
234
+ // 直接接続されたネットワークなら
235
+ ipPacketOutputToHost (outputdev , destAddr , packet )
236
+ } else if route .iptype == network {
237
+ // 直接つながっていないネットワークなら
238
+ ipPacketOutputToNetxhop (outputdev , destAddr , packet )
239
+ }
240
+ }
241
+
176
242
/*
177
243
IPパケットにカプセル化して送信
178
244
https://github.com/kametan0730/interface_2022_11/blob/master/chapter2/ip.cpp#L102
179
245
*/
180
- func ipPacketEncapsulate (inputdev * netDevice , destAddr , srcAddr uint32 , payload []byte , protocolType uint8 ) {
246
+ func ipPacketEncapsulateOutput (inputdev * netDevice , destAddr , srcAddr uint32 , payload []byte , protocolType uint8 ) {
181
247
var ipPacket []byte
182
248
183
249
// IPヘッダで必要なIPパケットの全長を算出する
@@ -203,15 +269,14 @@ func ipPacketEncapsulate(inputdev *netDevice, destAddr, srcAddr uint32, payload
203
269
// payloadを追加
204
270
ipPacket = append (ipPacket , payload ... )
205
271
206
- // Todo: ルートテーブルを検索して送信先IPのMACアドレスがなければ、
272
+ // ルートテーブルを検索して送信先IPのMACアドレスがなければ、
207
273
// ARPリクエストを生成して送信して結果を受信してから、ethernetからパケットを送る
208
274
destMacAddr := searchArpTableEntry (destAddr )
209
275
if destMacAddr != [6 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 } {
210
276
// ルートテーブルに送信するIPアドレスのMACアドレスがあれば送信
211
- fmt .Println ("MACアドレスがあったので送信" )
212
277
ethernetOutput (inputdev , destMacAddr , ipPacket , ETHER_TYPE_IP )
213
278
} else {
214
- // Todo: ARPリクエストを出す
215
- fmt . Println ( "ARPリクエストを出す" )
279
+ // ARPリクエストを出す
280
+ sendArpRequest ( inputdev , destAddr )
216
281
}
217
282
}
0 commit comments