lixd / mydocker

参考《自己动手写 docker》从零开始实现一个简易的 docker 以及相关教程。Build a simple Docker from scratch along with related tutorials.
https://www.lixueduan.com/categories/docker/
MIT License
319 stars 35 forks source link

关于第16讲 #5

Closed ChenMiaoQiu closed 1 month ago

ChenMiaoQiu commented 1 month ago

network/ipam.go

1

// size - one是子网掩码后面的网络位数,2^(size - one)表示网段中的可用IP数
// 而2^(size - one)等价于1 << uint8(size - one)
(*ipam.Subnets)[subnet.String()] = strings.Repeat("0", 1<<uint8(size-one))

此处可用ip数是否需要变更为

(*ipam.Subnets)[subnet.String()] = strings.Repeat("0", 1<<(size-one)-2)

自动扣除网关和广播地址

2

for t := uint(4); t > 0; t -= 1 {
[]byte(ip)[4-t] += uint8(c >> ((t - 1) * 8))
}
// /由于此处IP是从1开始分配的(0被网关占了),所以最后再加1,最终得到分配的IP 172.17.0.20
ip[3] += 1

此处代码是否要修改为

cnt := c + 1
for t := uint(4); t > 0; t-- {
ip[4-t] += uint8(cnt >> ((t - 1) * 8))
}

不应该直接在ip[3]处+1,如果计算出的ip[3]为255,+1的话ip[3]会变为0 例:172.16.0.0/12 数组序号为255

package main

import (
    "fmt"
    "net"
)

func main() {
    _, subnet, _ := net.ParseCIDR("172.16.0.0/12")
    ip := subnet.IP
    c := 255
    fmt.Println(ip)
    for t := uint(4); t > 0; t-- {
        []byte(ip)[4-t] += uint8(c >> ((t - 1) * 8))
    }
    ip[3]++
    fmt.Println(ip)
}

输出为

172.16.0.0
172.16.0.0

修改后

package main

import (
    "fmt"
    "net"
)

func main() {
    _, subnet, _ := net.ParseCIDR("172.16.0.0/12")
    ip := subnet.IP
    c := 255
    c++
    fmt.Println(ip)
    for t := uint(4); t > 0; t-- {
        []byte(ip)[4-t] += uint8(c >> ((t - 1) * 8))
    }
    fmt.Println(ip)
}

输出为

172.16.0.0
172.16.1.0
lixd commented 1 month ago

看了下 2 这种写法确实会存在溢出问题,修改后写法可以解决溢出问题,不过有会出现 ip 超过网段的问题。 感觉最好还是在 1 上处理,直接初始化时把 0 和 255 位置设置为 1,根本上解决问题。

        ipCount := 1 << uint8(size-one)
        ipalloc := strings.Repeat("0", ipCount-2) // 减去 0和 255这俩个不可分配地址,所有可分配的 IP 地址
        // 初始化分配配置,标记 .0 和 .255 位置为不可分配,直接置为 1
        (*ipam.Subnets)[subnet.String()] = fmt.Sprintf("1%s1", ipalloc)