github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/drivers/windows/overlay/ov_network_windows.go (about)

     1  package overlay
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net"
     7  	"strconv"
     8  	"strings"
     9  	"sync"
    10  
    11  	"github.com/Microsoft/hcsshim"
    12  	"github.com/docker/libnetwork/driverapi"
    13  	"github.com/docker/libnetwork/netlabel"
    14  	"github.com/docker/libnetwork/portmapper"
    15  	"github.com/docker/libnetwork/types"
    16  	"github.com/sirupsen/logrus"
    17  )
    18  
    19  var (
    20  	hostMode  bool
    21  	networkMu sync.Mutex
    22  )
    23  
    24  type networkTable map[string]*network
    25  
    26  type subnet struct {
    27  	vni      uint32
    28  	subnetIP *net.IPNet
    29  	gwIP     *net.IP
    30  }
    31  
    32  type subnetJSON struct {
    33  	SubnetIP string
    34  	GwIP     string
    35  	Vni      uint32
    36  }
    37  
    38  type network struct {
    39  	id              string
    40  	name            string
    41  	hnsID           string
    42  	providerAddress string
    43  	interfaceName   string
    44  	endpoints       endpointTable
    45  	driver          *driver
    46  	initEpoch       int
    47  	initErr         error
    48  	subnets         []*subnet
    49  	secure          bool
    50  	portMapper      *portmapper.PortMapper
    51  	sync.Mutex
    52  }
    53  
    54  func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
    55  	return nil, types.NotImplementedErrorf("not implemented")
    56  }
    57  
    58  func (d *driver) NetworkFree(id string) error {
    59  	return types.NotImplementedErrorf("not implemented")
    60  }
    61  
    62  func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
    63  	var (
    64  		networkName   string
    65  		interfaceName string
    66  		staleNetworks []string
    67  	)
    68  
    69  	if id == "" {
    70  		return fmt.Errorf("invalid network id")
    71  	}
    72  
    73  	if nInfo == nil {
    74  		return fmt.Errorf("invalid network info structure")
    75  	}
    76  
    77  	if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
    78  		return types.BadRequestErrorf("ipv4 pool is empty")
    79  	}
    80  
    81  	staleNetworks = make([]string, 0)
    82  	vnis := make([]uint32, 0, len(ipV4Data))
    83  
    84  	existingNetwork := d.network(id)
    85  	if existingNetwork != nil {
    86  		logrus.Debugf("Network preexists. Deleting %s", id)
    87  		err := d.DeleteNetwork(id)
    88  		if err != nil {
    89  			logrus.Errorf("Error deleting stale network %s", err.Error())
    90  		}
    91  	}
    92  
    93  	n := &network{
    94  		id:         id,
    95  		driver:     d,
    96  		endpoints:  endpointTable{},
    97  		subnets:    []*subnet{},
    98  		portMapper: portmapper.New(""),
    99  	}
   100  
   101  	genData, ok := option[netlabel.GenericData].(map[string]string)
   102  
   103  	if !ok {
   104  		return fmt.Errorf("Unknown generic data option")
   105  	}
   106  
   107  	for label, value := range genData {
   108  		switch label {
   109  		case "com.docker.network.windowsshim.networkname":
   110  			networkName = value
   111  		case "com.docker.network.windowsshim.interface":
   112  			interfaceName = value
   113  		case "com.docker.network.windowsshim.hnsid":
   114  			n.hnsID = value
   115  		case netlabel.OverlayVxlanIDList:
   116  			vniStrings := strings.Split(value, ",")
   117  			for _, vniStr := range vniStrings {
   118  				vni, err := strconv.Atoi(vniStr)
   119  				if err != nil {
   120  					return fmt.Errorf("invalid vxlan id value %q passed", vniStr)
   121  				}
   122  
   123  				vnis = append(vnis, uint32(vni))
   124  			}
   125  		}
   126  	}
   127  
   128  	// If we are getting vnis from libnetwork, either we get for
   129  	// all subnets or none.
   130  	if len(vnis) < len(ipV4Data) {
   131  		return fmt.Errorf("insufficient vnis(%d) passed to overlay. Windows driver requires VNIs to be prepopulated", len(vnis))
   132  	}
   133  
   134  	for i, ipd := range ipV4Data {
   135  		s := &subnet{
   136  			subnetIP: ipd.Pool,
   137  			gwIP:     &ipd.Gateway.IP,
   138  		}
   139  
   140  		if len(vnis) != 0 {
   141  			s.vni = vnis[i]
   142  		}
   143  
   144  		d.Lock()
   145  		for _, network := range d.networks {
   146  			found := false
   147  			for _, sub := range network.subnets {
   148  				if sub.vni == s.vni {
   149  					staleNetworks = append(staleNetworks, network.id)
   150  					found = true
   151  					break
   152  				}
   153  			}
   154  			if found {
   155  				break
   156  			}
   157  		}
   158  		d.Unlock()
   159  
   160  		n.subnets = append(n.subnets, s)
   161  	}
   162  
   163  	for _, staleNetwork := range staleNetworks {
   164  		d.DeleteNetwork(staleNetwork)
   165  	}
   166  
   167  	n.name = networkName
   168  	if n.name == "" {
   169  		n.name = id
   170  	}
   171  
   172  	n.interfaceName = interfaceName
   173  
   174  	if nInfo != nil {
   175  		if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil {
   176  			return err
   177  		}
   178  	}
   179  
   180  	d.addNetwork(n)
   181  
   182  	err := d.createHnsNetwork(n)
   183  
   184  	if err != nil {
   185  		d.deleteNetwork(id)
   186  	} else {
   187  		genData["com.docker.network.windowsshim.hnsid"] = n.hnsID
   188  	}
   189  
   190  	return err
   191  }
   192  
   193  func (d *driver) DeleteNetwork(nid string) error {
   194  	if nid == "" {
   195  		return fmt.Errorf("invalid network id")
   196  	}
   197  
   198  	n := d.network(nid)
   199  	if n == nil {
   200  		return types.ForbiddenErrorf("could not find network with id %s", nid)
   201  	}
   202  
   203  	_, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsID, "")
   204  	if err != nil {
   205  		return types.ForbiddenErrorf(err.Error())
   206  	}
   207  
   208  	d.deleteNetwork(nid)
   209  
   210  	return nil
   211  }
   212  
   213  func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
   214  	return nil
   215  }
   216  
   217  func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
   218  	return nil
   219  }
   220  
   221  func (d *driver) addNetwork(n *network) {
   222  	d.Lock()
   223  	d.networks[n.id] = n
   224  	d.Unlock()
   225  }
   226  
   227  func (d *driver) deleteNetwork(nid string) {
   228  	d.Lock()
   229  	delete(d.networks, nid)
   230  	d.Unlock()
   231  }
   232  
   233  func (d *driver) network(nid string) *network {
   234  	d.Lock()
   235  	defer d.Unlock()
   236  	return d.networks[nid]
   237  }
   238  
   239  // func (n *network) restoreNetworkEndpoints() error {
   240  // 	logrus.Infof("Restoring endpoints for overlay network: %s", n.id)
   241  
   242  // 	hnsresponse, err := hcsshim.HNSListEndpointRequest("GET", "", "")
   243  // 	if err != nil {
   244  // 		return err
   245  // 	}
   246  
   247  // 	for _, endpoint := range hnsresponse {
   248  // 		if endpoint.VirtualNetwork != n.hnsID {
   249  // 			continue
   250  // 		}
   251  
   252  // 		ep := n.convertToOverlayEndpoint(&endpoint)
   253  
   254  // 		if ep != nil {
   255  // 			logrus.Debugf("Restored endpoint:%s Remote:%t", ep.id, ep.remote)
   256  // 			n.addEndpoint(ep)
   257  // 		}
   258  // 	}
   259  
   260  // 	return nil
   261  // }
   262  
   263  func (n *network) convertToOverlayEndpoint(v *hcsshim.HNSEndpoint) *endpoint {
   264  	ep := &endpoint{
   265  		id:        v.Name,
   266  		profileID: v.Id,
   267  		nid:       n.id,
   268  		remote:    v.IsRemoteEndpoint,
   269  	}
   270  
   271  	mac, err := net.ParseMAC(v.MacAddress)
   272  
   273  	if err != nil {
   274  		return nil
   275  	}
   276  
   277  	ep.mac = mac
   278  	ep.addr = &net.IPNet{
   279  		IP:   v.IPAddress,
   280  		Mask: net.CIDRMask(32, 32),
   281  	}
   282  
   283  	return ep
   284  }
   285  
   286  func (d *driver) createHnsNetwork(n *network) error {
   287  
   288  	subnets := []hcsshim.Subnet{}
   289  
   290  	for _, s := range n.subnets {
   291  		subnet := hcsshim.Subnet{
   292  			AddressPrefix: s.subnetIP.String(),
   293  		}
   294  
   295  		if s.gwIP != nil {
   296  			subnet.GatewayAddress = s.gwIP.String()
   297  		}
   298  
   299  		vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
   300  			Type: "VSID",
   301  			VSID: uint(s.vni),
   302  		})
   303  
   304  		if err != nil {
   305  			return err
   306  		}
   307  
   308  		subnet.Policies = append(subnet.Policies, vsidPolicy)
   309  		subnets = append(subnets, subnet)
   310  	}
   311  
   312  	network := &hcsshim.HNSNetwork{
   313  		Name:               n.name,
   314  		Type:               d.Type(),
   315  		Subnets:            subnets,
   316  		NetworkAdapterName: n.interfaceName,
   317  		AutomaticDNS:       true,
   318  	}
   319  
   320  	configurationb, err := json.Marshal(network)
   321  	if err != nil {
   322  		return err
   323  	}
   324  
   325  	configuration := string(configurationb)
   326  	logrus.Infof("HNSNetwork Request =%v", configuration)
   327  
   328  	hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
   329  	if err != nil {
   330  		return err
   331  	}
   332  
   333  	n.hnsID = hnsresponse.Id
   334  	n.providerAddress = hnsresponse.ManagementIP
   335  
   336  	return nil
   337  }
   338  
   339  // contains return true if the passed ip belongs to one the network's
   340  // subnets
   341  func (n *network) contains(ip net.IP) bool {
   342  	for _, s := range n.subnets {
   343  		if s.subnetIP.Contains(ip) {
   344  			return true
   345  		}
   346  	}
   347  
   348  	return false
   349  }
   350  
   351  // getSubnetforIP returns the subnet to which the given IP belongs
   352  func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
   353  	for _, s := range n.subnets {
   354  		// first check if the mask lengths are the same
   355  		i, _ := s.subnetIP.Mask.Size()
   356  		j, _ := ip.Mask.Size()
   357  		if i != j {
   358  			continue
   359  		}
   360  		if s.subnetIP.Contains(ip.IP) {
   361  			return s
   362  		}
   363  	}
   364  	return nil
   365  }
   366  
   367  // getMatchingSubnet return the network's subnet that matches the input
   368  func (n *network) getMatchingSubnet(ip *net.IPNet) *subnet {
   369  	if ip == nil {
   370  		return nil
   371  	}
   372  	for _, s := range n.subnets {
   373  		// first check if the mask lengths are the same
   374  		i, _ := s.subnetIP.Mask.Size()
   375  		j, _ := ip.Mask.Size()
   376  		if i != j {
   377  			continue
   378  		}
   379  		if s.subnetIP.IP.Equal(ip.IP) {
   380  			return s
   381  		}
   382  	}
   383  	return nil
   384  }