golang socket框架_go netty

golang socket框架_go netty1. 简介 先简略的介绍下 Bridge,它是一个虚拟的网络设备,linux 内核已经实现了该网络设备的功能。所以我们可以直接通过命令就能创建出 Bridge。很多人为了更好的理解 Bridge 这个

前置知识:希望您对 Linux Namespace 有所了解,以及一些基础的网络知识。

1. 简介

  • 先简略的介绍下 Bridge,它是一个虚拟的网络设备,linux 内核已经实现了该网络设备的功能。所以我们可以直接通过命令就能创建出 Bridge。很多人为了更好的理解 Bridge 这个网络设备都会将它类比成 交换机,但其实这种理解会很容易误导且对其他网络设备的理解会形成障碍。其实 Bridge 它就是一种协议或者是一种类型,进行实例化后形成二层网络设备对象,而网络设备分为二层三层设备。

  • Net Namespace是实现网络虚拟化的重要功能,它能创建多个隔离的网络空间,它们有独自的网络栈信息。不管是虚拟机还是容器,运行的时候仿佛自己就在独立的网络中。什么是Linux Namespace ?

  • 最后同步一个概念

    • 二层交换:使用 MAC 地址进行通信;
    • 三层交换:使用 IP 地址进行通信,IP就需要网关(下一跳地址);

2. Linux 环境实验

实验环境 Centos7.9 (3.10.0-1160.el7.x86_64)

2.1 NetNamespace 间通信

  • 图示,这种做法只是为了展示namespace 之间通信,生产上很少出现这样的场景;

image.png

  • Console (实验)
    # 创建net namespace, ns0 和 ns1
    > ip netns add ns0
    > ip netns add ns1
    > ip netns list
    ns1 (id: 1)
    ns0 (id: 0)
    
    # 创建 veth 以太对设备,这是一个成对出现的设备,用于在两个net namespace中传输数据
    # 创建一个veth0 和 veth1 并将veth1绑定在 ns1 中
    > ip link add veth0 type veth peer name veth1 netns ns1
    # 将 veth0 绑定到 ns0
    > ip link set veth0 netns ns0
    
    # 查看 ns0 设备, 两个设备都为 DOWN
    > ip -n ns0 link
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    11: veth0@if10: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
        link/ether 2e:73:f7:b1:52:c2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    
    # 为两个veth设置地址,并启用 lo,veth
    > ip -n ns0 addr add 10.0.1.1/24 dev veth0
    > ip -n ns0 link set veth0 up
    > ip -n ns0 link set lo up
    
    > ip -n ns1 addr add 10.0.1.2/24 dev veth1
    > ip -n ns1 link set veth1 up
    > ip -n ns1 link set lo up
    
    # 最后做ping测试
    > ip netns exec ns1 ping 10.0.1.1
    PING 10.0.1.1 (10.0.1.1) 56(84) bytes of data.
    64 bytes from 10.0.1.1: icmp_seq=1 ttl=64 time=0.232 ms
    
    > ip netns exec ns0 ping 10.0.1.2
    PING 10.0.1.2 (10.0.1.2) 56(84) bytes of data.
    64 bytes from 10.0.1.2: icmp_seq=1 ttl=64 time=0.293 ms
    

2.2 Bridge、NetNamespace、Localhost 通信

  • 这种做法是一种常态做法,在K8s 和 Docker中都是常见的场景;下面会顺带解析二层mac交换与三层IP交换;架构图示:

image.png

  • Console(实验),图中有3个namespace,下面实验只建立两个做示范

    # 安装bridge 查看工具
    > yum install -y bridge-utils
    
    # 创建 bridge (创建bridge默认创建一个vlan1),绑定一个IP后启用它。
    > ip link add bridge0 type bridge
    > ip addr add 10.0.1.254/24 dev bridge0
    > ip link set  bridge0 up
    
    # 创建 net0 namespace,并创建veth(和第一个实验类似)
    > ip netns add net0
    # 创建 veth 将eth0 放入 net0
    > ip link add veth0 type veth peer name eth0 netns net0
    # 将veth0 绑定到 bridge0 上
    > ip link set veth0 master bridge0
    # 为 eth0 绑定ip地址
    > ip -n net0 addr add 10.0.1.1/24 dev eth0 brd +
    # 启动设备
    > ip -n net0 link set dev eth0 up
    > ip -n net0 link set dev lo up
    > ip link set dev veth0 up
    # 查看net0设备情况
    > ip -n net0 link
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
        ...
    2: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
        link/ether 46:ed:ec:f0:63:07 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 10.0.1.1/24 scope global eth0
        ...
    
    # 这里在说一个知识点 eth0@if18 的 if18对应的是主namespace 下 ip link 的18号设备,如果你删除外面的这个以太对设备,那么net0里面的也会一并删除。
    > ip link
    ...
    18: veth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master bridge0 state UP mode DEFAULT group default qlen 1000
        link/ether 0e:d5:0e:0c:e7:73 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    ...
    
    
    # 下面是创建net1的操作
    > ip netns add net1
    > ip link add veth1 type veth peer name eth1 netns net1
    > ip link set veth1 master bridge0
    > ip -n net1 addr add 10.0.1.2/24 dev eth0 brd +
    > ip -n net1 link set dev eth1 up
    > ip -n net1 link set dev lo up
    > ip link set dev veth1 up
    
    # 查看现在bridge0 中拥有的veth设备数量,可以看到是2个
    > brctl show bridge0
    bridge name	bridge id		STP enabled	interfaces
    bridge0		8000.0ed50e0ce773	no		veth0
                                                            veth1
    
  • 下面进行bridge0 内 netns 互通测试,可以看到是没有问题

    # ip netns exec net0 ping 10.0.1.2
    PING 10.0.1.2 (10.0.1.2) 56(84) bytes of data.
    64 bytes from 10.0.1.2: icmp_seq=1 ttl=64 time=0.061 ms
    64 bytes from 10.0.1.2: icmp_seq=2 ttl=64 time=0.080 ms
    ...
    
    # 这是通过二层mac寻址(二层交换),可以看看在linux上如何查看他们
    # net0上来记录对端的mac地址以及ip地址
    > ip netns exec net0 ip neigh
    10.0.1.2 dev eth0 lladdr 56:01:64:48:c3:87 STALE
    10.0.1.254 dev eth0 lladdr 0e:d5:0e:0c:e7:73 STALE
    
    # 可以看到net1 的mac地址 56:01:64:48:c3:87
    >ip -n net1 link
    ...
    2: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
        link/ether 56:01:64:48:c3:87 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    
  • 那我们继续测试netns 与 LocalHost 主机是否互通,我这里的主机地址是192.168.0.3

    > ip netns exec net0 ping  192.168.0.3
    connect: 网络不可达
    

    OMG,可以看到 netns 到达主机是不通。因为 net0 所在网段是10.0.1.0/24 这个网段,而我的主机网段是192.168.0.0/24,二层广播域也是不通的所以无法进行二层交换。(还有一点是net0是通过bridge0连接主机,而bridge0本身再创建的时候默认划分了一个vlan1。)

    由此我们应该想到就是走三层交换,即通过路由寻址。

    # 分别给给net0、net1 加上默认路由, 所有流量下一跳都走 10.0.1.254 由eth0 出。
    > ip netns exec net0 ip route add default via 10.0.1.254 dev eth0
    > ip netns exec net1 ip route add default via 10.0.1.254 dev eth0
    
    # 查看net0 的路由
    > ip netns exec net0 route -n
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    0.0.0.0         10.0.1.254      0.0.0.0         UG    0      0        0 eth0
    10.0.1.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
    
    # 还需要一条在主机上回包的路由,去往10.0.1.0/24网段的流量走 10.0.1.254 由bridge0这个设备出
    # 先删除创建bridge时系统自动创建的一条默认路由
    > ip route del 10.0.1.0/24
    > ip route add 10.0.1.0/24 via 10.0.1.254 dev bridge0
    # 查看主机的路由
    > route -n
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    0.0.0.0         192.168.0.1     0.0.0.0         UG    100    0        0 eth0
    10.0.1.0        10.0.1.254      255.255.255.0   UG    0      0        0 bridge0
    192.168.0.0     0.0.0.0         255.255.255.0   U     100    0        0 eth0
    
    # 再测试下
    > ip netns exec net0 ping  192.168.0.3
    PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
    64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.061 ms
    64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.080 ms
    

    PS: 写路由时由哪个设备出是很重要的,由于不同的网络设备对数据包会做不同的封装。

2.3 Bridge、NetNamespace、RemoteHost 通信

  • 上个小节写了实现了前面三种,这次只需要实现Remotehost通信即可。如果理解上面一节的三层交换含义,那么就能得知跨主机通信也是需要三层交换。

2.3.1 实验

  • 架构图

    * 主机A: 192.168.0.3;net0 网段:10.0.1.0/24
    * 主机B: 192.168.0.2;net0 网段:10.0.2.0/24
    * 默认网关: 192.168.0.1
    * 实验内容: 两台机器的net0 namespace间互通,相当于 10.0.1.1 需要 ping 通 10.0.1.2;以及10.0.1.1 ping 通 192.168.0.2
    

image.png

  • 构建出 net0 到本机的互通 (192.168.0.3)

    # 和上一个实验是一样的流程配置即可
    
    
  • 构建出 net0 到本机的互通 (192.168.0.2)

    # bridge #
    > ip link add dev bridge0 type bridge
    > ip link set dev bridge0 up
    > ip addr add 10.0.2.254/24 dev bridge0
    # net0 #
    > ip netns add net0
    > ip link add dev veth0 type veth peer name eth0 netns net0
    # brd + 是设置 10.0.2.255 为广播地址
    > ip -n net0 addr add 10.0.2.1/24 dev eth0 brd +
    > ip -n net0 link set dev eth0 up
    > ip -n net0 link set dev lo up
    > ip link set dev veth0 master bridge0
    > ip link set dev veth0 up
    # 查看 veth0 bridge0 都是up
    > ip link
    # 配置net0 默认路由
    >  ip netns exec net0 ip route add default via 10.0.2.254 dev eth0
    # 配置主机路由
    > ip route del  10.0.2.0/24
    > ip route add  10.0.2.0/24 via 10.0.2.254 dev bridge0
    # ping 通测试
    > ip netns exec net0 ping 192.168.0.2
    
  • 到此两台机器的net0都是可以ping 通主机的出口IP,下面正式进行跨主机联通;

  • net0 (10.0.1.1) -> 主机(192.168.0.2)-> GW (192.168.0.,1)

    • 通过iptables进行伪装发送即可,这样的做法即可以把网络包发送到网关和ping通主机,但是还不能解决跨主机的namespace通信。
      # 这里其实有两种做法
      # 。
      # 192.168.0.3
      > echo 1 > /proc/sys/net/ipv4/ip_forward
      > iptables -t nat -A POSTROUTING -s 10.0.1.0/24 -j MASQUERADE
      # 192.168.0.2
      > echo 1 > /proc/sys/net/ipv4/ip_forward
      > iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -j MASQUERADE
      
      # 现在就可以测试 ping
      > ip netns exec net0 ping 192.168.0.2
      
  • net0 (10.0.1.1) -> 主机(192.168.0.2)-> net0 (10.0.2.1)

    • 其实最简单的办法就是再两个机器上都各自写一条路由,做三层交换即可

      # 192.168.0.3
      > ip route del 10.0.1.0/24
      # 直接为目标 10.0.2.0 的网段指定下一跳
      > ip route 10.0.2.0/24 via 192.168.0.2 dev eth0
      
      # 192.168.0.2
      > ip route del 10.0.2.0/24
      # 直接为目标 10.0.1.0 的网段指定下一跳
      > ip route 10.0.1.0/24 via 192.168.0.3 dev eth0
      
      # 测试 ping 主机
      > ip netns exec net0 ping 192.168.0.2
      # 测试 net0 (10.0.2.1)
      > ip netns exec net0 ping 10.0.2.1
      

3. 代码演示

  • 这里使用用了3个库来完成代码的开发 netlinknetnsgo-iptables,废了一番功夫倒腾出来了,整个程序是幂等的,也就是可以多次运行结果都是一样的;

3.1 安装库

> go get "github.com/coreos/go-iptables/iptables"
> go get "github.com/vishvananda/netlink"

3.2 代码

  • netfilter_study.go,最终允许是分别在两台主机上运行的,实现了2.3.1的效果,代码都比较简单结合注释和末尾会有一些难点解析。
    package main
    
    import (
            "fmt"
            "github.com/coreos/go-iptables/iptables"
            "github.com/vishvananda/netlink"
            "github.com/vishvananda/netns"
            "log"
            "net"
            "os"
            "os/exec"
            "runtime"
    )
    
    /* #实验环境# 主机A: HOST: 192.168.0.3 ns0: 10.0.1.1/24 bridge0: 10.0.1.254/24 主机B: HOST: 192.168.0.2 ns0: 10.0.2.1/24 bridge0: 10.0.2.254/24 #实现目标# 10.0.1.1 -> 192.168.0.2 10.0.1.1 -> 10.0.2.1 */
    
    var (
            IsHostA = false
    )
    
    const (
            EnvName = "IS_HOST_A"
            // 无需修改
            NSName     = "ns0"
            BridgeName = "bridge0"
            VEth0      = "veth0"
            NsEth0     = "nseth0"
            
            // 如果需要在自己的机器上实现,需要改动HostA 和 HostB 变量即可
            HostA        = "192.168.0.3/24"
            HostANS0     = "10.0.1.1/24"
            HostABridge0 = "10.0.1.254/24"
    
            HostB        = "192.168.0.2/24"
            HostBNS0     = "10.0.2.1/24"
            HostBBridge0 = "10.0.2.254/24"
    )
    
    func Error(e error) {
            if e != nil {
                    log.Fatalln(e)
            }
    }
    
    type DoFunc func(oNs, nNs *netns.NsHandle) error
    
    func SetupBridge() *netlink.Bridge {
            log.Println("SetupBridge...runing")
            linkDev, _ := netlink.LinkByName(BridgeName)
    
            if linkDev != nil {
                    if _, ok := linkDev.(*netlink.Bridge); ok {
                            Error(netlink.LinkDel(linkDev))
                    }
            }
    
            br0 := &netlink.Bridge{
                    LinkAttrs: netlink.LinkAttrs{
                            Name:   BridgeName,
                            MTU:    1500,
                            TxQLen: -1,
                    },
            }
            // 添加
            Error(netlink.LinkAdd(br0))
            // 启动
            Error(netlink.LinkSetUp(br0))
            // 设置ip
            hb := HostABridge0
            if !IsHostA {
                    hb = HostBBridge0
            }
    
            ipv4Net, err := netlink.ParseIPNet(hb)
            Error(err)
            Error(netlink.AddrAdd(br0, &netlink.Addr{
                    IPNet: ipv4Net,
            }))
            log.Println("SetupBridge...done")
            return br0
    }
    
    func SetupNetNamespace() *netns.NsHandle {
            runtime.LockOSThread()
            defer runtime.UnlockOSThread()
            log.Println("SetupNetNamespace...running")
            origns, _ := netns.Get()
            defer origns.Close()
            _, err := netns.GetFromName(NSName)
            Error(netns.Set(origns))
    
            if err == nil {
                    log.Printf("%s net ns is exists. Delete netns %s\n", NSName, NSName)
                    cmd := exec.Command(
                            "sh",
                            "-c",
                            fmt.Sprintf("/usr/sbin/ip netns del %s", NSName))
                    Error(cmd.Run())
            }
    
            // 由于程序上启动netns 是需要附着于进程上的,所以这里直接使用 ip netns 来创建net namespace
            cmd := exec.Command("sh", "-c", fmt.Sprintf("/usr/sbin/ip netns add %s", NSName))
            Error(cmd.Run())
            ns, err := netns.GetFromName(NSName)
            Error(err)
            log.Println("SetupNetNamespace...done")
            return &ns
    }
    
    func SetupVEthPeer(br *netlink.Bridge, ns *netns.NsHandle) {
            log.Println("SetupVEth...running")
    
            oBrVEth, _ := netlink.LinkByName(VEth0)
            if oBrVEth != nil {
                    log.Printf("%s is exists, it will be delete. \n", VEth0)
                    Error(netlink.LinkDel(oBrVEth))
            }
    
            log.Printf("Create vethpeer %s peer name %s\n", VEth0, NsEth0)
            vethPeer := &netlink.Veth{
                    LinkAttrs: netlink.LinkAttrs{
                            Name: VEth0,
                    },
                    PeerName: NsEth0,
            }
    
            Error(netlink.LinkAdd(vethPeer))
    
            log.Printf("Set %s to %s \n", vethPeer.PeerName, NSName)
            // 获取 ns 的 veth
            nsVeth, err := netlink.LinkByName(vethPeer.PeerName)
            Error(err)
            // 设置ns 的 veth
            Error(netlink.LinkSetNsFd(nsVeth, int(*ns)))
    
            log.Printf("Set %s master to %s \n", vethPeer.Name, BridgeName)
            // 获取 host 的 veth
            brVeth, err := netlink.LinkByName(vethPeer.Name)
            Error(err)
            // 设置 bridge 的 veth
            Error(netlink.LinkSetMaster(brVeth, br))
            log.Printf("Set up %s \n", vethPeer.Name)
            Error(netlink.LinkSetUp(brVeth))
    
            Error(NsDo(func(oNs, nNs *netns.NsHandle) error {
                    // 设置IP地址
                    hn := HostANS0
                    if !IsHostA {
                            hn = HostBNS0
                    }
                    log.Printf("Addr add ip to %s \n", vethPeer.Name)
                    ipv4Net, err := netlink.ParseIPNet(hn)
                    Error(err)
                    Error(netlink.AddrAdd(nsVeth, &netlink.Addr{
                            IPNet: ipv4Net,
                    }))
                    log.Printf("Set up %s \n", vethPeer.PeerName)
                    // 启动设备
                    Error(netlink.LinkSetUp(nsVeth))
    
                    log.Println("SetupVEth...done")
                    return nil
            }))
    
    }
    
    func SetupNsDefaultRoute() {
            Error(NsDo(func(oNs, nNs *netns.NsHandle) error {
    
                    // add default gate way
                    log.Println("SetupNsDefaultRouter... running")
                    log.Printf("Add net namespace %s default gateway.", NSName)
    
                    gwAddr := HostBBridge0
                    if IsHostA {
                            gwAddr = HostABridge0
                    }
    
                    gw, err := netlink.ParseIPNet(gwAddr)
                    Error(err)
    
                    defaultRoute := &netlink.Route{
                            Dst: nil,
                            Gw:  gw.IP,
                    }
    
                    Error(netlink.RouteAdd(defaultRoute))
                    log.Println("SetupNsDefaultRouter... done")
                    return nil
            }))
    }
    
    func SetupIPTables() {
            log.Println("Setup IPTables for ns transfer packet to remote host...running")
            // 读取本地iptables,默认是ipv4
            ipt, err := iptables.New()
            Error(err)
            // iptables -t nat -A POSTROUTING -s 10.0.1.0/24 -j MASQUERADE
            nsAddr := HostBNS0
            if IsHostA {
                    nsAddr = HostANS0
            }
            _, srcNet, err := net.ParseCIDR(nsAddr)
            Error(err)
    
            rule := []string{"-s", srcNet.String(), "-j", "MASQUERADE"}
            // 先进行清除后再添加,保持简易幂等
            _ = ipt.Delete("nat", "POSTROUTING", rule...)
            Error(ipt.Append("nat", "POSTROUTING", rule...))
            log.Println("Setup IPTables done")
    }
    
    func SetupRouteNs2Ns() {
            log.Println("Setup route HostA(net0) <==> HostB(net0)... running")
            // 10.0.1.0/24 via 192.168.0.3 dev eth0
            gwAddr := HostA
            dstAddr := HostANS0
            if IsHostA {
                    gwAddr = HostB
                    dstAddr = HostBNS0
            }
    
    
            _, dstNet, err := net.ParseCIDR(dstAddr)
            Error(err)
    
            gwNet, err := netlink.ParseIPNet(gwAddr)
            Error(err)
    
            // 先删除后增加
            _ =  netlink.RouteDel(&netlink.Route{
                    LinkIndex: netlink.NewLinkAttrs().Index,
                    Dst:       dstNet,
            })
    
            Error(netlink.RouteAdd(&netlink.Route{
                    LinkIndex: netlink.NewLinkAttrs().Index,
                    Dst:       dstNet,
                    Gw:        gwNet.IP,
            }))
    
            log.Println("Setup route HostA(net0) <==> HostB(net0) done")
    }
    
    func NsDo(doFunc DoFunc) error {
            // 进入netns, 使用线程锁固定当前routine 不会其他线程执行,避免namespace 执行出现异常。
            // 因为如果在执行过程中切换了线程,可能找不到已经建立好的namespace。
            runtime.LockOSThread()
            defer runtime.UnlockOSThread()
    
            log.Printf("Switch net namespace to %s \n", NSName)
            originNs, err := netns.Get()
            Error(err)
            // 切换回原始ns
            defer func() {
                    log.Println("Switch net namespace to origin")
                    Error(netns.Set(originNs))
            }()
    
            ns, err := netns.GetFromName(NSName)
            Error(err)
    
            Error(netns.Set(ns))
            return doFunc(&originNs, &ns)
    }
    
    func main() {
    
            if os.Getenv(EnvName) == "1" {
                    IsHostA = true
            }
            ns := SetupNetNamespace()
            bridge := SetupBridge()
            SetupVEthPeer(bridge, ns)
            SetupNsDefaultRoute()
            SetupIPTables()
            SetupRouteNs2Ns()
            log.Println("Config Finished.")
    }
    
    
    • 从名字上看基本和之前在命令的使用是一致的,创建namespace、bridge 和 vethpeer 然后进行veth绑定,最后配置路由和iptables。
    • 唯一有个疑点是在 NsDo 这个函数,这个函数是一个必包函数,主要为了锁定线程;在go里,每个操作系统线程都可能对应不同的network namespace,但由于go线程调度机制的特点,在我们的代码逻辑开始执行的时候,并不能够保证当前的network namespace就是我们创建的或者是我们开始时候的namespace,这样会导致我们不知道当前身处什么space下。(涉及知识点:GO调度模型(GPM)Linux Process Namespace

3.3 运行

  • 在HostA 上运行:export IS_HOST_A=1; go run netfilter_study.go
  • 在HostB 上运行:export IS_HOST_A=0; go run netfilter_study.go
  • 运行后效果,看到 Config Finished 即可。
    > export IS_HOST_A=1; go run netlink_study.go
    2022/03/14 17:23:58 SetupNetNamespace...running
    2022/03/14 17:23:58 ns0 net ns is exists. Delete netns ns0
    2022/03/14 17:23:58 SetupNetNamespace...done
    2022/03/14 17:23:58 SetupBridge...runing
    2022/03/14 17:23:58 SetupBridge...done
    2022/03/14 17:23:58 SetupVEth...running
    2022/03/14 17:23:58 veth0 is exists, it will be delete. 
    2022/03/14 17:23:58 Create vethpeer veth0 peer name nseth0
    2022/03/14 17:23:58 Set nseth0 to ns0 
    2022/03/14 17:23:58 Set veth0 master to bridge0 
    2022/03/14 17:23:58 Set up veth0 
    2022/03/14 17:23:58 Switch net namespace to ns0 
    2022/03/14 17:23:58 Addr add ip to veth0 
    2022/03/14 17:23:58 Set up nseth0 
    2022/03/14 17:23:58 SetupVEth...done
    2022/03/14 17:23:58 Switch net namespace to origin
    2022/03/14 17:23:58 Switch net namespace to ns0 
    2022/03/14 17:23:58 SetupNsDefaultRouter... running
    2022/03/14 17:23:58 Add net namespace ns0 default gateway.
    2022/03/14 17:23:58 SetupNsDefaultRouter... done
    2022/03/14 17:23:58 Switch net namespace to origin
    2022/03/14 17:23:58 Setup IPTables for ns transfer packet to remote host...running
    2022/03/14 17:23:58 Setup IPTables done
    2022/03/14 17:23:58 Setup route HostA(net0) <==> HostB(net0)... running
    2022/03/14 17:23:58 Setup route HostA(net0) <==> HostB(net0) done
    2022/03/14 17:23:58 Config Finished.
    
  • HostA上运行测试命令
    > ip netns exec ns0 ping 10.0.2.1
    

4. 写在最后

  • 之前我个人对linux网络设备的理解是误解,总以一种物理性质来理解它,比如一个网卡设备我很难理解为什么它还有子接口?如果将它以一种设备对象或软件化的去理解它就非常好理解。一个网卡设备默认有个主接口,那么相对应就可以创建子借口,再者想到网卡是一个多路复用和多路分解的网络设备,这样一来就容易消化了。

  • 网络设备的类型,需要明确知道那种类型是二层还是三层。好比实体化二层交换机只会包含二层类型的设备与协议, 三层交换机(核心交换)就包含了二层三层设备与协议。

  • 都看到这了给个再走吧。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13266.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注