github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/default_gateway.go (about) 1 package libnetwork 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/docker/libnetwork/netlabel" 8 "github.com/docker/libnetwork/types" 9 "github.com/sirupsen/logrus" 10 ) 11 12 const ( 13 gwEPlen = 12 14 ) 15 16 var procGwNetwork = make(chan (bool), 1) 17 18 /* 19 libnetwork creates a bridge network "docker_gw_bridge" for providing 20 default gateway for the containers if none of the container's endpoints 21 have GW set by the driver. ICC is set to false for the GW_bridge network. 22 23 If a driver can't provide external connectivity it can choose to not set 24 the GW IP for the endpoint. 25 26 endpoint on the GW_bridge network is managed dynamically by libnetwork. 27 ie: 28 - its created when an endpoint without GW joins the container 29 - its deleted when an endpoint with GW joins the container 30 */ 31 32 func (sb *sandbox) setupDefaultGW() error { 33 34 // check if the container already has a GW endpoint 35 if ep := sb.getEndpointInGWNetwork(); ep != nil { 36 return nil 37 } 38 39 c := sb.controller 40 41 // Look for default gw network. In case of error (includes not found), 42 // retry and create it if needed in a serialized execution. 43 n, err := c.NetworkByName(libnGWNetwork) 44 if err != nil { 45 if n, err = c.defaultGwNetwork(); err != nil { 46 return err 47 } 48 } 49 50 createOptions := []EndpointOption{CreateOptionAnonymous()} 51 52 var gwName string 53 if len(sb.containerID) <= gwEPlen { 54 gwName = "gateway_" + sb.containerID 55 } else { 56 gwName = "gateway_" + sb.id[:gwEPlen] 57 } 58 59 sbLabels := sb.Labels() 60 61 if sbLabels[netlabel.PortMap] != nil { 62 createOptions = append(createOptions, CreateOptionPortMapping(sbLabels[netlabel.PortMap].([]types.PortBinding))) 63 } 64 65 if sbLabels[netlabel.ExposedPorts] != nil { 66 createOptions = append(createOptions, CreateOptionExposedPorts(sbLabels[netlabel.ExposedPorts].([]types.TransportPort))) 67 } 68 69 epOption := getPlatformOption() 70 if epOption != nil { 71 createOptions = append(createOptions, epOption) 72 } 73 74 newEp, err := n.CreateEndpoint(gwName, createOptions...) 75 if err != nil { 76 return fmt.Errorf("container %s: endpoint create on GW Network failed: %v", sb.containerID, err) 77 } 78 79 defer func() { 80 if err != nil { 81 if err2 := newEp.Delete(true); err2 != nil { 82 logrus.Warnf("Failed to remove gw endpoint for container %s after failing to join the gateway network: %v", 83 sb.containerID, err2) 84 } 85 } 86 }() 87 88 epLocal := newEp.(*endpoint) 89 90 if err = epLocal.sbJoin(sb); err != nil { 91 return fmt.Errorf("container %s: endpoint join on GW Network failed: %v", sb.containerID, err) 92 } 93 94 return nil 95 } 96 97 // If present, detach and remove the endpoint connecting the sandbox to the default gw network. 98 func (sb *sandbox) clearDefaultGW() error { 99 var ep *endpoint 100 101 if ep = sb.getEndpointInGWNetwork(); ep == nil { 102 return nil 103 } 104 if err := ep.sbLeave(sb, false); err != nil { 105 return fmt.Errorf("container %s: endpoint leaving GW Network failed: %v", sb.containerID, err) 106 } 107 if err := ep.Delete(false); err != nil { 108 return fmt.Errorf("container %s: deleting endpoint on GW Network failed: %v", sb.containerID, err) 109 } 110 return nil 111 } 112 113 // Evaluate whether the sandbox requires a default gateway based 114 // on the endpoints to which it is connected. It does not account 115 // for the default gateway network endpoint. 116 117 func (sb *sandbox) needDefaultGW() bool { 118 var needGW bool 119 120 for _, ep := range sb.getConnectedEndpoints() { 121 if ep.endpointInGWNetwork() { 122 continue 123 } 124 if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" { 125 continue 126 } 127 if ep.getNetwork().Internal() { 128 continue 129 } 130 // During stale sandbox cleanup, joinInfo may be nil 131 if ep.joinInfo != nil && ep.joinInfo.disableGatewayService { 132 continue 133 } 134 // TODO v6 needs to be handled. 135 if len(ep.Gateway()) > 0 { 136 return false 137 } 138 for _, r := range ep.StaticRoutes() { 139 if r.Destination != nil && r.Destination.String() == "0.0.0.0/0" { 140 return false 141 } 142 } 143 needGW = true 144 } 145 146 return needGW 147 } 148 149 func (sb *sandbox) getEndpointInGWNetwork() *endpoint { 150 for _, ep := range sb.getConnectedEndpoints() { 151 if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") { 152 return ep 153 } 154 } 155 return nil 156 } 157 158 func (ep *endpoint) endpointInGWNetwork() bool { 159 if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") { 160 return true 161 } 162 return false 163 } 164 165 func (sb *sandbox) getEPwithoutGateway() *endpoint { 166 for _, ep := range sb.getConnectedEndpoints() { 167 if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" { 168 continue 169 } 170 if len(ep.Gateway()) == 0 { 171 return ep 172 } 173 } 174 return nil 175 } 176 177 // Looks for the default gw network and creates it if not there. 178 // Parallel executions are serialized. 179 func (c *controller) defaultGwNetwork() (Network, error) { 180 procGwNetwork <- true 181 defer func() { <-procGwNetwork }() 182 183 n, err := c.NetworkByName(libnGWNetwork) 184 if _, ok := err.(types.NotFoundError); ok { 185 n, err = c.createGWNetwork() 186 } 187 return n, err 188 } 189 190 // Returns the endpoint which is providing external connectivity to the sandbox 191 func (sb *sandbox) getGatewayEndpoint() *endpoint { 192 for _, ep := range sb.getConnectedEndpoints() { 193 if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" { 194 continue 195 } 196 if len(ep.Gateway()) != 0 { 197 return ep 198 } 199 } 200 return nil 201 }