github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/drivers/windows/overlay/ov_network_windows.go (about)

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