Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

replace macvlan with veth pairs #2414

Merged
merged 8 commits into from
Oct 15, 2024
2 changes: 1 addition & 1 deletion pkg/network/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func Attach(link netlink.Link, bridge *netlink.Bridge, vlan *uint16, name ...str
n = name[0]
}
//we need to create an veth pair to wire 2 bridges.
veth, err := ifaceutil.MakeVethPair(n, bridge.Name, 1500)
veth, err := ifaceutil.MakeVethPair(n, bridge.Name, 1500, "")
if err != nil {
return err
}
Expand Down
15 changes: 11 additions & 4 deletions pkg/network/ifaceutil/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,20 @@ func RandomName(prefix string) (string, error) {
}

// MakeVethPair creates a veth pair
func MakeVethPair(name, master string, mtu int) (netlink.Link, error) {
func MakeVethPair(name, master string, mtu int, peerPrefix string) (netlink.Link, error) {
masterLink, err := netlink.LinkByName(master)
if err != nil {
return nil, err
return nil, fmt.Errorf("master link: %s not found: %v", master, err)
}
peer := ""
if peerPrefix == "" {
peer = fmt.Sprintf("p-%s", name)
} else {
peer = fmt.Sprintf("%s-%s", peerPrefix, name)
}
if len(peer) > 15 {
peer = peer[0:15]
}

peer := fmt.Sprintf("%s-p", name)
veth := &netlink.Veth{
LinkAttrs: netlink.LinkAttrs{
Name: name,
Expand Down
130 changes: 100 additions & 30 deletions pkg/network/networker.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/threefoldtech/zos/pkg/network/iperf"
"github.com/threefoldtech/zos/pkg/network/mycelium"
"github.com/threefoldtech/zos/pkg/network/ndmz"
"github.com/threefoldtech/zos/pkg/network/options"
"github.com/threefoldtech/zos/pkg/network/public"
"github.com/threefoldtech/zos/pkg/network/tuntap"
"github.com/threefoldtech/zos/pkg/network/wireguard"
Expand Down Expand Up @@ -156,28 +157,54 @@ func (n *networker) attachYgg(id string, netNs ns.NetNS) (net.IPNet, error) {
return net.IPNet{}, fmt.Errorf("failed to generate ygg subnet IP: %w", err)
}

ips := []*net.IPNet{
&ip,
}

gw, err := n.ygg.Gateway()
if err != nil {
return net.IPNet{}, fmt.Errorf("failed to get ygg gateway IP: %w", err)
}

routes := []*netlink.Route{
{
Dst: &net.IPNet{
IP: net.ParseIP("200::"),
Mask: net.CIDRMask(7, 128),
},
Gw: gw.IP,
// LinkIndex:... this is set by macvlan.Install
route := netlink.Route{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think even if this now has only a single route. It's important to understand that this won't always be the case. It's totally legal to configure multiple routes and taking away this ability is not recommended.

Dst: &net.IPNet{
IP: net.ParseIP("200::"),
Mask: net.CIDRMask(7, 128),
},
Gw: gw.IP,
}

if err := n.createMacVlan(ZDBYggIface, types.YggBridge, hw, ips, routes, netNs); err != nil {
return net.IPNet{}, errors.Wrap(err, "failed to setup zdb ygg interface")
name := filepath.Base(netNs.Path())
peerPrefix := name
if len(name) > 4 {
peerPrefix = name[0:4]
}

if !ifaceutil.Exists(ZDBYggIface, netNs) {
yggLink, err := ifaceutil.MakeVethPair(ZDBYggIface, types.YggBridge, 1500, peerPrefix)
if err != nil {
return net.IPNet{}, fmt.Errorf("failed to create ygg link: %w", err)
}

err = netlink.LinkSetNsFd(yggLink, int(netNs.Fd()))
if err != nil {
return net.IPNet{}, fmt.Errorf("failed to move ygg link: %s to namespace:%s : %w", ZDBYggIface, netNs.Path(), err)
}

if err := netNs.Do(func(_ ns.NetNS) error {
err = setLinkAddr(ZDBYggIface, &ip)
if err != nil {
return err
}

if err := ifaceutil.SetLoUp(); err != nil {
return fmt.Errorf("failed to set lo up for namespace '%s': %w", name, err)
}

if err := options.SetIPv6Forwarding(true); err != nil {
return fmt.Errorf("failed to enable ipv6 forwarding in namespace %q: %w", name, err)
}

return netlink.RouteAdd(&route)
}); err != nil {
return net.IPNet{}, fmt.Errorf("failed to setup link addresses %s: %w", ZDBYggIface, err)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

return ip, nil
Expand All @@ -199,7 +226,6 @@ func (n *networker) detachYgg(id string, netNs ns.NetNS) error {
func (n *networker) attachMycelium(id string, netNs ns.NetNS) (net.IPNet, error) {
// new hardware address for mycelium interface
hw := ifaceutil.HardwareAddrFromInputBytes([]byte("my:" + id))

myc, err := n.mycelium.InspectMycelium()
if err != nil {
return net.IPNet{}, err
Expand All @@ -210,34 +236,78 @@ func (n *networker) attachMycelium(id string, netNs ns.NetNS) (net.IPNet, error)
if err != nil {
return net.IPNet{}, fmt.Errorf("failed to generate mycelium IP: %w", err)
}

ips := []*net.IPNet{
&ip,
}

gw, err := myc.Gateway()
if err != nil {
return net.IPNet{}, fmt.Errorf("failed to get mycelium gateway IP: %w", err)
}

routes := []*netlink.Route{
{
Dst: &net.IPNet{
IP: net.ParseIP("400::"),
Mask: net.CIDRMask(7, 128),
},
Gw: gw.IP,
// LinkIndex:... this is set by macvlan.Install
route := netlink.Route{
Dst: &net.IPNet{
IP: net.ParseIP("400::"),
Mask: net.CIDRMask(7, 128),
},
Gw: gw.IP,
}

if err := n.createMacVlan(ZDBMyceliumIface, types.MyceliumBridge, hw, ips, routes, netNs); err != nil {
return net.IPNet{}, errors.Wrap(err, "failed to setup zdb mycelium interface")
name := filepath.Base(netNs.Path())
peerPrefix := name
if len(name) > 4 {
peerPrefix = name[0:4]
}
if !ifaceutil.Exists(ZDBMyceliumIface, netNs) {
myceliumLink, err := ifaceutil.MakeVethPair(ZDBMyceliumIface, types.MyceliumBridge, 1500, peerPrefix)
if err != nil {
return net.IPNet{}, fmt.Errorf("failed to create mycelium link: %w", err)
}
err = netlink.LinkSetNsFd(myceliumLink, int(netNs.Fd()))
if err != nil {
return net.IPNet{}, fmt.Errorf("failed to move mycelium link: %s to namespace:%s : %w", ZDBMyceliumIface, netNs.Path(), err)
}

if err := netNs.Do(func(_ ns.NetNS) error {
err = setLinkAddr(ZDBMyceliumIface, &ip)
if err != nil {
return err
}

if err := ifaceutil.SetLoUp(); err != nil {
return fmt.Errorf("failed to set lo up for namespace '%s': %w", name, err)
}

if err := options.SetIPv6Forwarding(true); err != nil {
return fmt.Errorf("failed to enable ipv6 forwarding in namespace %q: %w", name, err)
}

return netlink.RouteAdd(&route)
}); err != nil {
return net.IPNet{}, fmt.Errorf("failed to setup link addresses %s: %w", ZDBMyceliumIface, err)
}
}

return ip, nil
}

func setLinkAddr(name string, ip *net.IPNet) error {
link, err := netlink.LinkByName(name)
if err != nil {
return fmt.Errorf("failed to set link address: %w", err)
}

// if err := options.Set(name, options.IPv6Disable(false)); err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove unneeded commented coder

// return fmt.Errorf("failed to enable ip6 on interface %s: %w", name, err)
// }

addr := netlink.Addr{
IPNet: ip,
}
err = netlink.AddrAdd(link, &addr)
if err != nil && !os.IsExist(err) {
return fmt.Errorf("failed to add ip address to link: %w", err)
}

return netlink.LinkSetUp(link)
}

// ensurePrepare ensurets that a unique namespace is created (based on id) with "prefix"
// and make sure it's wired to the bridge on host namespace
func (n *networker) ensurePrepare(id, prefix, bridge string) (string, error) {
Expand Down
Loading