Skip to content

Commit

Permalink
windows: replace old netsh (rakelkar/gonetsh) with powershell commands
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasng committed May 30, 2020
1 parent 4ff77dc commit d31b0dc
Show file tree
Hide file tree
Showing 22 changed files with 544 additions and 1,056 deletions.
37 changes: 21 additions & 16 deletions backend/hostgw/hostgw_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ package hostgw

import (
"fmt"
"strconv"
"github.com/coreos/flannel/pkg/routing"
"sync"
"time"

Expand All @@ -26,12 +26,9 @@ import (
"github.com/coreos/flannel/subnet"
log "github.com/golang/glog"
"github.com/juju/errors"
"github.com/rakelkar/gonetsh/netroute"
"github.com/rakelkar/gonetsh/netsh"
"golang.org/x/net/context"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/apimachinery/pkg/util/wait"
utilexec "k8s.io/utils/exec"
)

func init() {
Expand Down Expand Up @@ -81,11 +78,11 @@ func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
Mtu: be.extIface.Iface.MTU,
LinkIndex: be.extIface.Iface.Index,
}
n.GetRoute = func(lease *subnet.Lease) *netroute.Route {
return &netroute.Route{
n.GetRoute = func(lease *subnet.Lease) *routing.Route {
return &routing.Route{
DestinationSubnet: lease.Subnet.ToIPNet(),
GatewayAddress: lease.Attrs.PublicIP.ToIP(),
LinkIndex: n.LinkIndex,
InterfaceIndex: n.LinkIndex,
}
}

Expand All @@ -108,7 +105,6 @@ func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,
}

// 3. Check if the network exists and has the expected settings
netshHelper := netsh.New(utilexec.New())
createNewNetwork := true
expectedSubnet := n.SubnetLease.Subnet
expectedAddressPrefix := expectedSubnet.String()
Expand Down Expand Up @@ -172,8 +168,13 @@ func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,

// Wait for the interface with the management IP
log.Infof("Waiting to get net interface for HNSNetwork %s (%s)", networkName, newNetwork.ManagementIP)
managementIP, err := ip.ParseIP4(newNetwork.ManagementIP)
if err != nil {
return nil, errors.Annotatef(err, "Failed to parse management ip (%s)", newNetwork.ManagementIP)
}

waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
_, lastErr = netshHelper.GetInterfaceByIP(newNetwork.ManagementIP)
_, lastErr = ip.GetInterfaceByIP(managementIP.ToIP())
return lastErr == nil, nil
})
if waitErr == wait.ErrWaitTimeout {
Expand Down Expand Up @@ -230,23 +231,27 @@ func (be *HostgwBackend) RegisterNetwork(ctx context.Context, wg sync.WaitGroup,

// 7. Enable forwarding on the host interface and endpoint
for _, interfaceIpAddress := range []string{expectedNetwork.ManagementIP, expectedBridgeEndpoint.IPAddress.String()} {
netInterface, err := netshHelper.GetInterfaceByIP(interfaceIpAddress)
ipv4, err := ip.ParseIP4(interfaceIpAddress)
if err != nil {
return nil, errors.Annotatef(err, "Failed to parse expected net interface ip (%s)", interfaceIpAddress)
}

netInterface, err := ip.GetInterfaceByIP(ipv4.ToIP())
if err != nil {
return nil, errors.Annotatef(err, "failed to find interface for IP Address %s", interfaceIpAddress)
}
log.Infof("Found %+v interface with IP %s", netInterface, interfaceIpAddress)

// When a new hns network is created, the interface is modified, esp the name, index
if expectedNetwork.ManagementIP == netInterface.IpAddress {
n.LinkIndex = netInterface.Idx
if expectedNetwork.ManagementIP == ipv4.String() {
n.LinkIndex = netInterface.Index
n.Name = netInterface.Name
}

interfaceIdx := strconv.Itoa(netInterface.Idx)
if err := netshHelper.EnableForwarding(interfaceIdx); err != nil {
return nil, errors.Annotatef(err, "failed to enable forwarding on %s index %s", netInterface.Name, interfaceIdx)
if err := ip.EnableForwardingForInterface(netInterface); err != nil {
return nil, errors.Annotatef(err, "failed to enable forwarding on %s index %d", netInterface.Name, netInterface.Index)
}
log.Infof("Enabled forwarding on %s index %s", netInterface.Name, interfaceIdx)
log.Infof("Enabled forwarding on %s index %d", netInterface.Name, netInterface.Index)
}

return n, nil
Expand Down
34 changes: 17 additions & 17 deletions backend/route_network_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import (
"time"

log "github.com/golang/glog"
"github.com/rakelkar/gonetsh/netroute"
"golang.org/x/net/context"

"github.com/coreos/flannel/pkg/routing"
"github.com/coreos/flannel/subnet"
"strings"
)
Expand All @@ -35,10 +35,10 @@ type RouteNetwork struct {
Name string
BackendType string
SM subnet.Manager
GetRoute func(lease *subnet.Lease) *netroute.Route
GetRoute func(lease *subnet.Lease) *routing.Route
Mtu int
LinkIndex int
routes []netroute.Route
routes []routing.Route
}

func (n *RouteNetwork) MTU() int {
Expand All @@ -56,7 +56,7 @@ func (n *RouteNetwork) Run(ctx context.Context) {
wg.Done()
}()

n.routes = make([]netroute.Route, 0, 10)
n.routes = make([]routing.Route, 0, 10)
wg.Add(1)
go func() {
n.routeCheck(ctx)
Expand All @@ -77,7 +77,7 @@ func (n *RouteNetwork) Run(ctx context.Context) {
}

func (n *RouteNetwork) handleSubnetEvents(batch []subnet.Event) {
netrouteHelper := netroute.New()
router := routing.RouterWindows{}

for _, evt := range batch {
leaseSubnet := evt.Lease.Subnet
Expand All @@ -93,22 +93,22 @@ func (n *RouteNetwork) handleSubnetEvents(batch []subnet.Event) {
case subnet.EventAdded:
log.Infof("Subnet added: %v via %v", leaseSubnet, leaseAttrs.PublicIP)

existingRoutes, _ := netrouteHelper.GetNetRoutes(expectedRoute.LinkIndex, expectedRoute.DestinationSubnet)
existingRoutes, _ := router.GetRoutesFromInterfaceToSubnet(expectedRoute.InterfaceIndex, expectedRoute.DestinationSubnet)
if len(existingRoutes) > 0 {
existingRoute := existingRoutes[0]
if existingRoute.Equal(*expectedRoute) {
continue
}

log.Warningf("Replacing existing route %v via %v with %v via %v", leaseSubnet, existingRoute.GatewayAddress, leaseSubnet, leaseAttrs.PublicIP)
err := netrouteHelper.RemoveNetRoute(existingRoute.LinkIndex, existingRoute.DestinationSubnet, existingRoute.GatewayAddress)
err := router.DeleteRoute(existingRoute.InterfaceIndex, existingRoute.DestinationSubnet, existingRoute.GatewayAddress)
if err != nil {
log.Errorf("Error removing route: %v", err)
continue
}
}

err := netrouteHelper.NewNetRoute(expectedRoute.LinkIndex, expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress)
err := router.CreateRoute(expectedRoute.InterfaceIndex, expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress)
if err != nil {
log.Errorf("Error creating route: %v", err)
continue
Expand All @@ -119,13 +119,13 @@ func (n *RouteNetwork) handleSubnetEvents(batch []subnet.Event) {
case subnet.EventRemoved:
log.Infof("Subnet removed: %v", leaseSubnet)

existingRoutes, _ := netrouteHelper.GetNetRoutes(expectedRoute.LinkIndex, expectedRoute.DestinationSubnet)
existingRoutes, _ := router.GetRoutesFromInterfaceToSubnet(expectedRoute.InterfaceIndex, expectedRoute.DestinationSubnet)
if len(existingRoutes) > 0 {
existingRoute := existingRoutes[0]
if existingRoute.Equal(*expectedRoute) {
log.Infof("Removing existing route %v via %v", leaseSubnet, existingRoute.GatewayAddress)

err := netrouteHelper.RemoveNetRoute(existingRoute.LinkIndex, existingRoute.DestinationSubnet, existingRoute.GatewayAddress)
err := router.DeleteRoute(existingRoute.InterfaceIndex, existingRoute.DestinationSubnet, existingRoute.GatewayAddress)
if err != nil {
log.Warningf("Error removing route: %v", err)
}
Expand All @@ -140,7 +140,7 @@ func (n *RouteNetwork) handleSubnetEvents(batch []subnet.Event) {
}
}

func (n *RouteNetwork) addToRouteList(newRoute *netroute.Route) {
func (n *RouteNetwork) addToRouteList(newRoute *routing.Route) {
for _, route := range n.routes {
if route.Equal(*newRoute) {
return
Expand All @@ -150,7 +150,7 @@ func (n *RouteNetwork) addToRouteList(newRoute *netroute.Route) {
n.routes = append(n.routes, *newRoute)
}

func (n *RouteNetwork) removeFromRouteList(oldRoute *netroute.Route) {
func (n *RouteNetwork) removeFromRouteList(oldRoute *routing.Route) {
for index, route := range n.routes {
if route.Equal(*oldRoute) {
n.routes = append(n.routes[:index], n.routes[index+1:]...)
Expand All @@ -171,9 +171,9 @@ func (n *RouteNetwork) routeCheck(ctx context.Context) {
}

func (n *RouteNetwork) checkSubnetExistInRoutes() {
netrouteHelper := netroute.New()
router := routing.RouterWindows{}

existingRoutes, err := netrouteHelper.GetNetRoutesAll()
existingRoutes, err := router.GetAllRoutes()
if err != nil {
log.Errorf("Error enumerating routes: %v", err)
return
Expand All @@ -188,12 +188,12 @@ func (n *RouteNetwork) checkSubnetExistInRoutes() {
}

if !exist {
err := netrouteHelper.NewNetRoute(expectedRoute.LinkIndex, expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress)
err := router.CreateRoute(expectedRoute.InterfaceIndex, expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress)
if err != nil {
log.Warningf("Error recovering route to %v via %v on %v (%v).", expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress, expectedRoute.LinkIndex, err)
log.Warningf("Error recovering route to %v via %v on %v (%v).", expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress, expectedRoute.InterfaceIndex, err)
continue
}
log.Infof("Recovered route to %v via %v on %v.", expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress, expectedRoute.LinkIndex)
log.Infof("Recovered route to %v via %v on %v.", expectedRoute.DestinationSubnet, expectedRoute.GatewayAddress, expectedRoute.InterfaceIndex)
}
}
}
11 changes: 7 additions & 4 deletions backend/vxlan/device_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build windows

package vxlan

Expand All @@ -20,9 +21,7 @@ import (
"github.com/coreos/flannel/pkg/ip"
log "github.com/golang/glog"
"github.com/juju/errors"
"github.com/rakelkar/gonetsh/netsh"
"k8s.io/apimachinery/pkg/util/wait"
utilexec "k8s.io/utils/exec"
"time"
)

Expand Down Expand Up @@ -132,10 +131,14 @@ func ensureNetwork(expectedNetwork *hcn.HostComputeNetwork, expectedAddressPrefi

managementIP := getManagementIP(newNetwork)
// Wait for the interface with the management IP
netshHelper := netsh.New(utilexec.New())
log.Infof("Waiting to get net interface for HostComputeNetwork %s (%s)", networkName, managementIP)
managementIPv4, err := ip.ParseIP4(managementIP)
if err != nil {
return nil, errors.Annotatef(err, "Failed to parse management ip (%s)", managementIP)
}

waitErr = wait.Poll(500*time.Millisecond, 5*time.Second, func() (done bool, err error) {
_, lastErr = netshHelper.GetInterfaceByIP(managementIP)
_, lastErr = ip.GetInterfaceByIP(managementIPv4.ToIP())
return lastErr == nil, nil
})
if waitErr == wait.ErrWaitTimeout {
Expand Down
8 changes: 4 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ func LookupExtIface(ifname string, ifregex string) (*backend.ExternalInterface,

// Check IP
for _, ifaceToMatch := range ifaces {
ifaceIP, err := ip.GetIfaceIP4Addr(&ifaceToMatch)
ifaceIP, err := ip.GetInterfaceIP4Addr(&ifaceToMatch)
if err != nil {
// Skip if there is no IPv4 address
continue
Expand Down Expand Up @@ -508,21 +508,21 @@ func LookupExtIface(ifname string, ifregex string) (*backend.ExternalInterface,
if iface == nil {
var availableFaces []string
for _, f := range ifaces {
ip, _ := ip.GetIfaceIP4Addr(&f) // We can safely ignore errors. We just won't log any ip
ip, _ := ip.GetInterfaceIP4Addr(&f) // We can safely ignore errors. We just won't log any ip
availableFaces = append(availableFaces, fmt.Sprintf("%s:%s", f.Name, ip))
}

return nil, fmt.Errorf("Could not match pattern %s to any of the available network interfaces (%s)", ifregex, strings.Join(availableFaces, ", "))
}
} else {
log.Info("Determining IP address of default interface")
if iface, err = ip.GetDefaultGatewayIface(); err != nil {
if iface, err = ip.GetDefaultGatewayInterface(); err != nil {
return nil, fmt.Errorf("failed to get default interface: %s", err)
}
}

if ifaceAddr == nil {
ifaceAddr, err = ip.GetIfaceIP4Addr(iface)
ifaceAddr, err = ip.GetInterfaceIP4Addr(iface)
if err != nil {
return nil, fmt.Errorf("failed to find IPv4 address for interface %s", iface.Name)
}
Expand Down
9 changes: 4 additions & 5 deletions pkg/ip/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !windows

package ip

Expand All @@ -36,7 +35,7 @@ func getIfaceAddrs(iface *net.Interface) ([]netlink.Addr, error) {
return netlink.AddrList(link, syscall.AF_INET)
}

func GetIfaceIP4Addr(iface *net.Interface) (net.IP, error) {
func GetInterfaceIP4Addr(iface *net.Interface) (net.IP, error) {
addrs, err := getIfaceAddrs(iface)
if err != nil {
return nil, err
Expand Down Expand Up @@ -67,7 +66,7 @@ func GetIfaceIP4Addr(iface *net.Interface) (net.IP, error) {
return nil, errors.New("No IPv4 address found for given interface")
}

func GetIfaceIP4AddrMatch(iface *net.Interface, matchAddr net.IP) error {
func GetInterfaceIP4AddrMatch(iface *net.Interface, matchAddr net.IP) error {
addrs, err := getIfaceAddrs(iface)
if err != nil {
return err
Expand All @@ -86,7 +85,7 @@ func GetIfaceIP4AddrMatch(iface *net.Interface, matchAddr net.IP) error {
return errors.New("No IPv4 address found for given interface")
}

func GetDefaultGatewayIface() (*net.Interface, error) {
func GetDefaultGatewayInterface() (*net.Interface, error) {
routes, err := netlink.RouteList(nil, syscall.AF_INET)
if err != nil {
return nil, err
Expand All @@ -111,7 +110,7 @@ func GetInterfaceByIP(ip net.IP) (*net.Interface, error) {
}

for _, iface := range ifaces {
err := GetIfaceIP4AddrMatch(&iface, ip)
err := GetInterfaceIP4AddrMatch(&iface, ip)
if err == nil {
return &iface, nil
}
Expand Down
Loading

0 comments on commit d31b0dc

Please sign in to comment.