func()

in controllers/daemon/staticgatewayconfiguration_controller.go [858:927]


func (r *StaticGatewayConfigurationReconciler) reconcileVethPairInHost(
	ctx context.Context,
	gwns ns.NetNS,
	snatIP string,
) error {
	log := log.FromContext(ctx)
	succeed := false

	la := netlink.NewLinkAttrs()
	la.Name = consts.HostVethLinkName

	mainLink, err := r.Netlink.LinkByName(la.Name)
	if _, ok := err.(netlink.LinkNotFoundError); ok {
		log.Info("Creating veth pair in host namespace")
		veth := &netlink.Veth{
			LinkAttrs: la,
			PeerName:  consts.HostLinkName,
		}
		err := r.Netlink.LinkAdd(veth)
		if err != nil {
			return fmt.Errorf("failed to add veth pair: %w", err)
		}
		defer func() {
			if !succeed {
				_ = r.Netlink.LinkDel(veth)
			}
		}()
		mainLink, err = r.Netlink.LinkByName(la.Name)
		if err != nil {
			return fmt.Errorf("failed to get veth link in host namespace after creation: %w", err)
		}
	} else if err != nil {
		return fmt.Errorf("failed to get veth link in host namespace: %w", err)
	}

	err = r.Netlink.LinkSetUp(mainLink)
	if err != nil {
		return fmt.Errorf("failed to set veth link in host namespace up: %w", err)
	}

	_, snatIPNet, err := net.ParseCIDR(snatIP + "/32")
	if err != nil {
		return fmt.Errorf("failed to parse SNAT IP %s: %w", snatIP+"/32", err)
	}
	route := &netlink.Route{
		LinkIndex: mainLink.Attrs().Index,
		Scope:     netlink.SCOPE_UNIVERSE,
		Dst:       snatIPNet,
	}
	if err = r.addOrReplaceRoute(ctx, route); err != nil {
		return fmt.Errorf("failed to create route to SNAT IP %s via gateway interface: %w", snatIP, err)
	}
	defer func() {
		if !succeed {
			_ = r.Netlink.RouteDel(route)
		}
	}()

	hostLink, err := r.Netlink.LinkByName(consts.HostLinkName)
	if err == nil {
		if err := r.Netlink.LinkSetNsFd(hostLink, int(gwns.Fd())); err != nil {
			return fmt.Errorf("failed to move veth peer link to gateway namespace: %w", err)
		}
	} else if _, ok := err.(netlink.LinkNotFoundError); !ok {
		return fmt.Errorf("failed to get veth peer link in host namespace: %w", err)
	}

	succeed = true
	return nil
}