github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/network/network.go (about) 1 // Copyright 2019 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package network 5 6 import ( 7 "fmt" 8 "math/rand" 9 "net" 10 "sort" 11 12 "github.com/juju/loggo" 13 ) 14 15 var logger = loggo.GetLogger("juju.core.network") 16 17 // macAddressTemplate is suitable for generating virtual MAC addresses, 18 // particularly for use by container devices. 19 // The last 3 segments are randomised. 20 // TODO (manadart 2018-06-21) Depending on where this is utilised, 21 // ensuring MAC address uniqueness within a model might be prudent. 22 const macAddressTemplate = "00:16:3e:%02x:%02x:%02x" 23 24 // GenerateVirtualMACAddress creates a random MAC address within the address 25 // space implied by macAddressTemplate above. 26 var GenerateVirtualMACAddress = func() string { 27 digits := make([]interface{}, 3) 28 for i := range digits { 29 digits[i] = rand.Intn(256) 30 } 31 return fmt.Sprintf(macAddressTemplate, digits...) 32 } 33 34 // Id defines a provider-specific network ID. 35 type Id string 36 37 // String returns the underlying string representation of the Id. 38 // This method helps with formatting and type inference. 39 func (id Id) String() string { 40 return string(id) 41 } 42 43 // IDSet represents the classic "set" data structure, and contains Id. 44 // IDSet is used as a typed version to prevent string -> Id -> string 45 // conversion when using set.Strings 46 type IDSet map[Id]struct{} 47 48 // MakeIDSet creates and initializes a IDSet and populates it with 49 // initial values as specified in the parameters. 50 func MakeIDSet(values ...Id) IDSet { 51 set := make(map[Id]struct{}, len(values)) 52 for _, id := range values { 53 set[id] = struct{}{} 54 } 55 return set 56 } 57 58 // Add puts a value into the set. 59 func (s IDSet) Add(value Id) { 60 s[value] = struct{}{} 61 } 62 63 // Size returns the number of elements in the set. 64 func (s IDSet) Size() int { 65 return len(s) 66 } 67 68 // IsEmpty is true for empty or uninitialized sets. 69 func (s IDSet) IsEmpty() bool { 70 return len(s) == 0 71 } 72 73 // Contains returns true if the value is in the set, and false otherwise. 74 func (s IDSet) Contains(id Id) bool { 75 _, exists := s[id] 76 return exists 77 } 78 79 // Difference returns a new IDSet representing all the values in the 80 // target that are not in the parameter. 81 func (s IDSet) Difference(other IDSet) IDSet { 82 result := make(IDSet) 83 // Use the internal map rather than going through the friendlier functions 84 // to avoid extra allocation of slices. 85 for value := range s { 86 if !other.Contains(value) { 87 result[value] = struct{}{} 88 } 89 } 90 return result 91 } 92 93 // Values returns an unordered slice containing all the values in the set. 94 func (s IDSet) Values() []Id { 95 result := make([]Id, len(s)) 96 i := 0 97 for key := range s { 98 result[i] = key 99 i++ 100 } 101 return result 102 } 103 104 // SortedValues returns an ordered slice containing all the values in the set. 105 func (s IDSet) SortedValues() []Id { 106 values := s.Values() 107 sort.Slice(values, func(i, j int) bool { 108 return values[i] < values[j] 109 }) 110 return values 111 } 112 113 // SubnetsForAddresses returns subnets corresponding to the addresses 114 // in the input address list. 115 // There can be situations (observed for CAAS) where the addresses can 116 // contain a FQDN. 117 // For these cases we log a warning and eschew subnet determination. 118 func SubnetsForAddresses(addrs []string) []string { 119 var subs []string 120 for _, a := range addrs { 121 // We don't expect this to be the case, but guard conservatively. 122 if _, _, err := net.ParseCIDR(a); err == nil { 123 subs = append(subs, a) 124 continue 125 } 126 127 if addr := net.ParseIP(a); addr != nil { 128 if addr.To4() != nil { 129 subs = append(subs, addr.String()+"/32") 130 } else { 131 subs = append(subs, addr.String()+"/128") 132 } 133 continue 134 } 135 136 logger.Warningf("unable to determine egress subnet for %q", a) 137 } 138 return subs 139 }