Skip to content

Commit 51265e8

Browse files
committedFeb 25, 2023
update
1 parent f8bfe9e commit 51265e8

File tree

4 files changed

+83
-15
lines changed

4 files changed

+83
-15
lines changed
 

‎chapter2.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ import (
77
"syscall"
88
)
99

10+
// Global変数でルーティングテーブルを宣言
11+
var iproute radixTreeNode
12+
1013
func runChapter2() {
1114
var netDeviceList []netDevice
12-
var iproute radixTreeNode
15+
1316
events := make([]syscall.EpollEvent, 10)
1417

1518
// epoll作成
@@ -62,10 +65,10 @@ func runChapter2() {
6265
ipdev: getIPdevice(netaddrs),
6366
}
6467

65-
// 直接接続ネットワークの経路を設定
68+
// 直接接続ネットワークの経路をルートテーブルのエントリに設定
6669
routeEntry := ipRouteEntry{
67-
ipRouteType: true,
68-
netdev: &netdev,
70+
iptype: connected,
71+
netdev: &netdev,
6972
}
7073
prefixLen := subnetToPrefixLen(netdev.ipdev.netmask)
7174
iproute.radixTreeAdd(netdev.ipdev.address&netdev.ipdev.netmask, prefixLen, routeEntry)

‎icmp.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,6 @@ func icmpInput(inputdev *netDevice, sourceAddr, destAddr uint32, icmpPacket []by
9191
fmt.Println("ICMP ECHO REPLY is received")
9292
case ICMP_TYPE_ECHO_REQUEST:
9393
fmt.Println("ICMP ECHO REQUEST is received, Create Reply Packet")
94-
ipPacketEncapsulate(inputdev, sourceAddr, destAddr, icmpmsg.ToPacket(), IP_PROTOCOL_NUM_ICMP)
94+
ipPacketEncapsulateOutput(inputdev, sourceAddr, destAddr, icmpmsg.ToPacket(), IP_PROTOCOL_NUM_ICMP)
9595
}
9696
}

‎ip.go

+73-8
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,17 @@ type ipHeader struct {
3333
destAddr uint32 // 送信先IPアドレス
3434
}
3535

36+
type ipRouteType uint8
37+
38+
const (
39+
connected ipRouteType = iota
40+
network
41+
)
42+
3643
type ipRouteEntry struct {
37-
ipRouteType bool
38-
netdev *netDevice
39-
nexthop uint32
44+
iptype ipRouteType
45+
netdev *netDevice
46+
nexthop uint32
4047
}
4148

4249
func (ipheader ipHeader) ToPacket() (ipHeaderByte []byte) {
@@ -173,11 +180,70 @@ func ipInputToOurs(inputdev *netDevice, ipheader ipHeader, packet []byte) {
173180
}
174181
}
175182

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+
176242
/*
177243
IPパケットにカプセル化して送信
178244
https://github.com/kametan0730/interface_2022_11/blob/master/chapter2/ip.cpp#L102
179245
*/
180-
func ipPacketEncapsulate(inputdev *netDevice, destAddr, srcAddr uint32, payload []byte, protocolType uint8) {
246+
func ipPacketEncapsulateOutput(inputdev *netDevice, destAddr, srcAddr uint32, payload []byte, protocolType uint8) {
181247
var ipPacket []byte
182248

183249
// IPヘッダで必要なIPパケットの全長を算出する
@@ -203,15 +269,14 @@ func ipPacketEncapsulate(inputdev *netDevice, destAddr, srcAddr uint32, payload
203269
// payloadを追加
204270
ipPacket = append(ipPacket, payload...)
205271

206-
// Todo: ルートテーブルを検索して送信先IPのMACアドレスがなければ、
272+
// ルートテーブルを検索して送信先IPのMACアドレスがなければ、
207273
// ARPリクエストを生成して送信して結果を受信してから、ethernetからパケットを送る
208274
destMacAddr := searchArpTableEntry(destAddr)
209275
if destMacAddr != [6]uint8{0, 0, 0, 0, 0, 0} {
210276
// ルートテーブルに送信するIPアドレスのMACアドレスがあれば送信
211-
fmt.Println("MACアドレスがあったので送信")
212277
ethernetOutput(inputdev, destMacAddr, ipPacket, ETHER_TYPE_IP)
213278
} else {
214-
// Todo: ARPリクエストを出す
215-
fmt.Println("ARPリクエストを出す")
279+
// ARPリクエストを出す
280+
sendArpRequest(inputdev, destAddr)
216281
}
217282
}

‎radix_tree.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ type radixTreeNode struct {
1010
value int
1111
}
1212

13-
func (node *radixTreeNode) radixTreeAdd(prefixIpAddr, prefixlen uint32, entryData ipRouteEntry) {
13+
func (node *radixTreeNode) radixTreeAdd(prefixIpAddr, prefixLen uint32, entryData ipRouteEntry) {
1414
// ルートノードから辿る
1515
current := node
1616
// 枝を辿る
17-
for i := 1; i <= int(prefixlen); i++ {
17+
for i := 1; i <= int(prefixLen); i++ {
1818
if prefixIpAddr>>(32-i)&0x01 == 1 { // 上からiビット目が1なら
1919
if current.node1 == nil {
2020
current.node1 = &radixTreeNode{

0 commit comments

Comments
 (0)
Please sign in to comment.