github.com/elfadel/cilium@v1.6.12/pkg/proxy/proxy.go (about) 1 // Copyright 2016-2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package proxy 16 17 import ( 18 "fmt" 19 "math/rand" 20 "time" 21 22 "github.com/cilium/cilium/api/v1/models" 23 "github.com/cilium/cilium/pkg/completion" 24 "github.com/cilium/cilium/pkg/envoy" 25 "github.com/cilium/cilium/pkg/lock" 26 "github.com/cilium/cilium/pkg/logging" 27 "github.com/cilium/cilium/pkg/logging/logfields" 28 "github.com/cilium/cilium/pkg/metrics" 29 "github.com/cilium/cilium/pkg/node" 30 "github.com/cilium/cilium/pkg/policy" 31 "github.com/cilium/cilium/pkg/proxy/logger" 32 "github.com/cilium/cilium/pkg/revert" 33 34 "github.com/sirupsen/logrus" 35 ) 36 37 var ( 38 log = logging.DefaultLogger.WithField(logfields.LogSubsys, "proxy") 39 ) 40 41 // field names used while logging 42 const ( 43 fieldMarker = "marker" 44 fieldSocket = "socket" 45 fieldFd = "fd" 46 fieldProxyRedirectID = "id" 47 48 // portReuseDelay is the delay until a port is being reused 49 portReuseDelay = 5 * time.Minute 50 51 // redirectCreationAttempts is the number of attempts to create a redirect 52 redirectCreationAttempts = 5 53 ) 54 55 type DatapathUpdater interface { 56 InstallProxyRules(proxyPort uint16, ingress bool, name string) error 57 RemoveProxyRules(proxyPort uint16, ingress bool, name string) error 58 SupportsOriginalSourceAddr() bool 59 } 60 61 type ProxyPort struct { 62 // Listener name (immutable) 63 name string 64 // isStatic is true when the listener on the proxy port is incapable 65 // of stopping and/or being reconfigured with a new proxy port once it has been 66 // first started. Set 'true' by SetProxyPort(), which is only called for 67 // static listeners (currently only DNS proxy). 68 isStatic bool 69 // parser type this port applies to (immutable) 70 parserType policy.L7ParserType 71 // 'true' for ingress, 'false' for egress (immutable) 72 ingress bool 73 // ProxyPort is the desired proxy listening port number. 74 proxyPort uint16 75 // nRedirects is the number of redirects using this proxy port 76 nRedirects int 77 // Configured is true when the proxy is (being) configured, but not necessarily 78 // acknowledged yet. This is reset to false when the underlying proxy listener 79 // is removed. 80 configured bool 81 // rulesPort congains the proxy port value configured to the datapath rules and 82 // is non-zero when a proxy has been successfully created and the 83 // datapath rules have been created. 84 rulesPort uint16 85 } 86 87 // Proxy maintains state about redirects 88 type Proxy struct { 89 *envoy.XDSServer 90 91 // stateDir is the path of the directory where the state of L7 proxies is 92 // stored. 93 stateDir string 94 95 // mutex is the lock required when modifying any proxy datastructure 96 mutex lock.RWMutex 97 98 // rangeMin is the minimum port used for proxy port allocation 99 rangeMin uint16 100 101 // rangeMax is the maximum port used for proxy port allocation. 102 // If port is unspecified, the proxy will automatically allocate 103 // ports out of the rangeMin-rangeMax range. 104 rangeMax uint16 105 106 // redirects is the map of all redirect configurations indexed by 107 // the redirect identifier. Redirects may be implemented by different 108 // proxies. 109 redirects map[string]*Redirect 110 111 // Datapath updater for installing and removing proxy rules for a single 112 // proxy port 113 datapathUpdater DatapathUpdater 114 } 115 116 // StartProxySupport starts the servers to support L7 proxies: xDS GRPC server 117 // and access log server. 118 func StartProxySupport(minPort uint16, maxPort uint16, stateDir string, 119 accessLogFile string, accessLogNotifier logger.LogRecordNotifier, accessLogMetadata []string, 120 datapathUpdater DatapathUpdater) *Proxy { 121 xdsServer := envoy.StartXDSServer(stateDir) 122 123 if accessLogFile != "" { 124 if err := logger.OpenLogfile(accessLogFile); err != nil { 125 log.WithError(err).WithField(logfields.Path, accessLogFile). 126 Warn("Cannot open L7 access log") 127 } 128 } 129 130 if accessLogNotifier != nil { 131 logger.SetNotifier(accessLogNotifier) 132 } 133 134 if len(accessLogMetadata) > 0 { 135 logger.SetMetadata(accessLogMetadata) 136 } 137 138 envoy.StartAccessLogServer(stateDir, xdsServer, DefaultEndpointInfoRegistry) 139 140 return &Proxy{ 141 XDSServer: xdsServer, 142 stateDir: stateDir, 143 rangeMin: minPort, 144 rangeMax: maxPort, 145 redirects: make(map[string]*Redirect), 146 datapathUpdater: datapathUpdater, 147 } 148 } 149 150 var ( 151 // proxyPortsMutex protects access to allocatedPorts, portRandomized, and proxyPorts 152 proxyPortsMutex lock.Mutex 153 154 // allocatedPorts is the map of all allocated proxy ports 155 allocatedPorts = make(map[uint16]struct{}) 156 157 portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano())) 158 159 // proxyPorts is a slice of all supported proxy ports 160 // The number and order of entries are fixed, and the fields 161 // initialized here are immutable. 162 proxyPorts = []ProxyPort{ 163 { 164 parserType: policy.ParserTypeHTTP, 165 ingress: false, 166 name: "cilium-http-egress", 167 }, 168 { 169 parserType: policy.ParserTypeHTTP, 170 ingress: true, 171 name: "cilium-http-ingress", 172 }, 173 { 174 parserType: policy.ParserTypeKafka, 175 ingress: false, 176 name: "cilium-kafka-egress", 177 }, 178 { 179 parserType: policy.ParserTypeKafka, 180 ingress: true, 181 name: "cilium-kafka-ingress", 182 }, 183 { 184 parserType: policy.ParserTypeDNS, 185 ingress: false, 186 name: "cilium-dns-egress", 187 }, 188 { 189 parserType: policy.ParserTypeNone, 190 ingress: false, 191 name: "cilium-proxylib-egress", 192 }, 193 { 194 parserType: policy.ParserTypeNone, 195 ingress: true, 196 name: "cilium-proxylib-ingress", 197 }, 198 } 199 ) 200 201 // Called with proxyPortsMutex held! 202 func isPortAvailable(openLocalPorts map[uint16]struct{}, port uint16) bool { 203 if _, used := allocatedPorts[port]; used { 204 return false // port already used 205 } 206 if port == 0 { 207 return false // zero port requested 208 } 209 // Check that the port is not already open 210 if _, alreadyOpen := openLocalPorts[port]; alreadyOpen { 211 return false // port already open 212 } 213 214 return true 215 } 216 217 // Called with proxyPortsMutex held! 218 func allocatePort(port, min, max uint16) (uint16, error) { 219 // Get a snapshot of the TCP and UDP ports already open locally. 220 openLocalPorts := readOpenLocalPorts(append(procNetTCPFiles, procNetUDPFiles...)) 221 222 if isPortAvailable(openLocalPorts, port) { 223 return port, nil 224 } 225 226 // TODO: Maybe not create a large permutation each time? 227 for _, r := range portRandomizer.Perm(int(max - min + 1)) { 228 resPort := uint16(r) + min 229 230 if isPortAvailable(openLocalPorts, resPort) { 231 return resPort, nil 232 } 233 } 234 235 return 0, fmt.Errorf("no available proxy ports") 236 } 237 238 // Called with proxyPortsMutex held! 239 func (pp *ProxyPort) reservePort() { 240 if !pp.configured { 241 allocatedPorts[pp.proxyPort] = struct{}{} 242 pp.configured = true 243 } 244 } 245 246 // Called with proxyPortsMutex held! 247 func findProxyPort(name string) *ProxyPort { 248 for i := range proxyPorts { 249 if proxyPorts[i].name == name { 250 return &proxyPorts[i] 251 } 252 } 253 return nil 254 } 255 256 // ackProxyPort() marks the proxy as successfully created and creates or updates the datapath rules 257 // accordingly. Each call must eventually be paired with a corresponding releaseProxyPort() call 258 // to keep the use count up-to-date. 259 // Must be called with proxyPortsMutex held! 260 func (p *Proxy) ackProxyPort(pp *ProxyPort) error { 261 if pp.nRedirects == 0 { 262 scopedLog := log.WithField("proxy port name", pp.name) 263 scopedLog.Debugf("Considering updating proxy port rules for %s:%d (old: %d)", pp.name, pp.proxyPort, pp.rulesPort) 264 265 // Datapath rules are added only after we know the proxy configuration 266 // with the actual port number has succeeded. Deletion of the rules 267 // is delayed after the redirects have been removed to the point 268 // when we know the port number changes. This is to reduce the churn 269 // in the datapath, but means that the datapath rules may exist even 270 // if the proxy is not currently configured. 271 272 // Remove old rules, if any and for different port 273 if pp.rulesPort != 0 && pp.rulesPort != pp.proxyPort { 274 scopedLog.Infof("Removing old proxy port rules for %s:%d", pp.name, pp.rulesPort) 275 p.datapathUpdater.RemoveProxyRules(pp.rulesPort, pp.ingress, pp.name) 276 pp.rulesPort = 0 277 } 278 // Add new rules, if needed 279 if pp.rulesPort != pp.proxyPort { 280 // This should always succeed if we have managed to start-up properly 281 scopedLog.Infof("Adding new proxy port rules for %s:%d", pp.name, pp.proxyPort) 282 err := p.datapathUpdater.InstallProxyRules(pp.proxyPort, pp.ingress, pp.name) 283 if err != nil { 284 return fmt.Errorf("Can't install proxy rules for %s: %s", pp.name, err) 285 } 286 } 287 pp.rulesPort = pp.proxyPort 288 } 289 pp.nRedirects++ 290 return nil 291 } 292 293 // releaseProxyPort() decreases the use count and frees the port if no users remain 294 // Must be called with proxyPortsMutex held! 295 func (p *Proxy) releaseProxyPort(name string) error { 296 pp := findProxyPort(name) 297 if pp == nil { 298 return fmt.Errorf("Can't find proxy port %s", name) 299 } 300 if pp.nRedirects == 0 { 301 return fmt.Errorf("Can't release proxy port: proxy %s on %d has refcount 0", name, pp.proxyPort) 302 } 303 304 pp.nRedirects-- 305 if pp.nRedirects == 0 { 306 if pp.isStatic { 307 return fmt.Errorf("Can't release proxy port: proxy %s on %d has a static listener", name, pp.proxyPort) 308 } 309 delete(allocatedPorts, pp.proxyPort) 310 // Force new port allocation the next time this ProxyPort is used. 311 pp.configured = false 312 // Leave the datapath rules behind on the hope that they get reused later. 313 // This becomes possible when we are able to keep the proxy listeners 314 // configured also when there are no redirects. 315 log.WithField(fieldProxyRedirectID, name).Debugf("Delayed release of proxy port %d", pp.proxyPort) 316 } 317 318 return nil 319 } 320 321 // mutex need not be held, as this only refers to immutable members in the static slice. 322 func getProxyPort(l7Type policy.L7ParserType, ingress bool) *ProxyPort { 323 portType := l7Type 324 switch l7Type { 325 case policy.ParserTypeDNS, policy.ParserTypeKafka, policy.ParserTypeHTTP: 326 default: 327 // "Unknown" parsers are assumed to be Proxylib (TCP) parsers, which 328 // is registered with an empty string. 329 portType = "" 330 } 331 // proxyPorts is small enough to not bother indexing it. 332 for i := range proxyPorts { 333 if proxyPorts[i].parserType == portType && proxyPorts[i].ingress == ingress { 334 return &proxyPorts[i] 335 } 336 } 337 return nil 338 } 339 340 func proxyNotFoundError(l7Type policy.L7ParserType, ingress bool) error { 341 dir := "egress" 342 if ingress { 343 dir = "ingress" 344 } 345 return fmt.Errorf("unrecognized %s proxy type: %s", dir, l7Type) 346 } 347 348 // Exported API 349 350 // GetProxyPort() returns the fixed listen port for a proxy, if any. 351 func GetProxyPort(l7Type policy.L7ParserType, ingress bool) (uint16, string, error) { 352 // Accessing pp.proxyPort requires the lock 353 proxyPortsMutex.Lock() 354 defer proxyPortsMutex.Unlock() 355 pp := getProxyPort(l7Type, ingress) 356 if pp != nil { 357 return pp.proxyPort, pp.name, nil 358 } 359 return 0, "", proxyNotFoundError(l7Type, ingress) 360 } 361 362 // SetProxyPort() marks the proxy 'name' as successfully created with proxy port 'port' and creates 363 // or updates the datapath rules accordingly. 364 // This should only be called for proxies that have a static listener that is already listening on 365 // 'port'. May only be called once per proxy. 366 func (p *Proxy) SetProxyPort(name string, port uint16) error { 367 proxyPortsMutex.Lock() 368 defer proxyPortsMutex.Unlock() 369 pp := findProxyPort(name) 370 if pp == nil { 371 return fmt.Errorf("Can't find proxy port %s", name) 372 } 373 if pp.nRedirects > 0 { 374 return fmt.Errorf("Can't set proxy port to %d: proxy %s is already configured on %d", port, name, pp.proxyPort) 375 } 376 pp.proxyPort = port 377 pp.isStatic = true // prevents release of the proxy port 378 pp.reservePort() // marks 'port' as reserved, 'pp' as configured 379 return p.ackProxyPort(pp) // creates datapath rules, increases the reference count 380 } 381 382 // ReinstallRules is called by daemon reconfiguration to re-install proxy ports rules that 383 // were removed during the removal of all Cilium rules. 384 func (p *Proxy) ReinstallRules() { 385 proxyPortsMutex.Lock() 386 defer proxyPortsMutex.Unlock() 387 for _, pp := range proxyPorts { 388 if pp.rulesPort > 0 { 389 // This should always succeed if we have managed to start-up properly 390 err := p.datapathUpdater.InstallProxyRules(pp.rulesPort, pp.ingress, pp.name) 391 if err != nil { 392 proxyPortsMutex.Unlock() 393 panic(fmt.Sprintf("Can't install proxy rules for %s: %s", pp.name, err)) 394 } 395 } 396 } 397 } 398 399 // CreateOrUpdateRedirect creates or updates a L4 redirect with corresponding 400 // proxy configuration. This will allocate a proxy port as required and launch 401 // a proxy instance. If the redirect is already in place, only the rules will be 402 // updated. 403 // The proxy listening port is returned, but proxy configuration on that port 404 // may still be ongoing asynchronously. Caller should wait for successful completion 405 // on 'wg' before assuming the returned proxy port is listening. 406 // Caller must call exactly one of the returned functions: 407 // - finalizeFunc to make the changes stick, or 408 // - revertFunc to cancel the changes. 409 func (p *Proxy) CreateOrUpdateRedirect(l4 *policy.L4Filter, id string, localEndpoint logger.EndpointUpdater, 410 wg *completion.WaitGroup) (proxyPort uint16, err error, finalizeFunc revert.FinalizeFunc, revertFunc revert.RevertFunc) { 411 412 p.mutex.Lock() 413 defer func() { 414 p.updateRedirectMetrics() 415 p.mutex.Unlock() 416 if err == nil && proxyPort == 0 { 417 panic("Trying to configure zero proxy port") 418 } 419 }() 420 421 scopedLog := log.WithField(fieldProxyRedirectID, id) 422 423 var revertStack revert.RevertStack 424 revertFunc = revertStack.Revert 425 426 if redir, ok := p.redirects[id]; ok { 427 redir.mutex.Lock() 428 429 if redir.listener.parserType == l4.L7Parser { 430 updateRevertFunc := redir.updateRules(l4) 431 revertStack.Push(updateRevertFunc) 432 var implUpdateRevertFunc revert.RevertFunc 433 implUpdateRevertFunc, err = redir.implementation.UpdateRules(wg, l4) 434 if err != nil { 435 redir.mutex.Unlock() 436 err = fmt.Errorf("unable to update existing redirect: %s", err) 437 return 0, err, nil, nil 438 } 439 revertStack.Push(implUpdateRevertFunc) 440 441 redir.lastUpdated = time.Now() 442 443 scopedLog.WithField(logfields.Object, logfields.Repr(redir)). 444 Debug("updated existing ", l4.L7Parser, " proxy instance") 445 446 redir.mutex.Unlock() 447 448 // Must return the proxy port when successful 449 proxyPort = redir.listener.proxyPort 450 return 451 } 452 453 var removeRevertFunc revert.RevertFunc 454 err, finalizeFunc, removeRevertFunc = p.removeRedirect(id, wg) 455 redir.mutex.Unlock() 456 457 if err != nil { 458 err = fmt.Errorf("unable to remove old redirect: %s", err) 459 return 0, err, nil, nil 460 } 461 462 revertStack.Push(removeRevertFunc) 463 } 464 465 proxyPortsMutex.Lock() 466 defer proxyPortsMutex.Unlock() 467 pp := getProxyPort(l4.L7Parser, l4.Ingress) 468 if pp == nil { 469 err = proxyNotFoundError(l4.L7Parser, l4.Ingress) 470 revertFunc() 471 return 0, err, nil, nil 472 } 473 474 redir := newRedirect(localEndpoint, pp, uint16(l4.Port)) 475 redir.updateRules(l4) 476 // Rely on create*Redirect to update rules, unlike the update case above. 477 478 for nRetry := 0; nRetry < redirectCreationAttempts; nRetry++ { 479 if nRetry > 0 { 480 // an error occurred and we can retry 481 scopedLog.WithError(err).Warningf("Unable to create %s proxy, retrying", pp.name) 482 } 483 484 if !pp.configured { 485 // Try allocate (the configured) port, but only if the proxy has not 486 // been already configured. 487 pp.proxyPort, err = allocatePort(pp.proxyPort, p.rangeMin, p.rangeMax) 488 if err != nil { 489 revertFunc() // Ignore errors while reverting. This is best-effort. 490 return 0, err, nil, nil 491 } 492 } 493 494 switch l4.L7Parser { 495 case policy.ParserTypeDNS: 496 redir.implementation, err = createDNSRedirect(redir, dnsConfiguration{}, DefaultEndpointInfoRegistry) 497 498 case policy.ParserTypeKafka: 499 redir.implementation, err = createKafkaRedirect(redir, kafkaConfiguration{}, DefaultEndpointInfoRegistry) 500 501 case policy.ParserTypeHTTP: 502 redir.implementation, err = createEnvoyRedirect(redir, p.stateDir, p.XDSServer, p.datapathUpdater.SupportsOriginalSourceAddr(), wg) 503 default: 504 redir.implementation, err = createEnvoyRedirect(redir, p.stateDir, p.XDSServer, p.datapathUpdater.SupportsOriginalSourceAddr(), wg) 505 } 506 507 if err == nil { 508 scopedLog.WithField(logfields.Object, logfields.Repr(redir)). 509 Debug("Created new ", l4.L7Parser, " proxy instance") 510 p.redirects[id] = redir 511 // must mark the proxyPort configured while we still hold the lock to prevent racing between 512 // two parallel runs 513 pp.reservePort() 514 515 revertStack.Push(func() error { 516 // Proxy port refcount has not been incremented yet, so it must not be decremented 517 // when reverting. Undo what we have done above. 518 p.mutex.Lock() 519 delete(p.redirects, id) 520 p.updateRedirectMetrics() 521 p.mutex.Unlock() 522 implFinalizeFunc, _ := redir.implementation.Close(wg) 523 if implFinalizeFunc != nil { 524 implFinalizeFunc() 525 } 526 return nil 527 }) 528 529 // Set the proxy port only after an ACK is received. 530 removeFinalizeFunc := finalizeFunc 531 finalizeFunc = func() { 532 if removeFinalizeFunc != nil { 533 removeFinalizeFunc() 534 } 535 536 proxyPortsMutex.Lock() 537 err := p.ackProxyPort(pp) 538 proxyPortsMutex.Unlock() 539 if err != nil { 540 // Finalize functions can't error out. This failure can only 541 // happen if there is an internal Cilium logic error regarding 542 // installation of iptables rules. 543 panic(err) 544 } 545 } 546 // Must return the proxy port when successful 547 proxyPort = pp.proxyPort 548 return 549 } 550 } 551 552 // an error occurred, and we have no more retries 553 scopedLog.WithError(err).Error("Unable to create ", l4.L7Parser, " proxy") 554 revertFunc() // Ignore errors while reverting. This is best-effort. 555 return 0, err, nil, nil 556 } 557 558 // RemoveRedirect removes an existing redirect that has been successfully created earlier. 559 func (p *Proxy) RemoveRedirect(id string, wg *completion.WaitGroup) (error, revert.FinalizeFunc, revert.RevertFunc) { 560 p.mutex.Lock() 561 defer func() { 562 p.updateRedirectMetrics() 563 p.mutex.Unlock() 564 }() 565 return p.removeRedirect(id, wg) 566 } 567 568 // removeRedirect removes an existing redirect. p.mutex must be held 569 // p.mutex must NOT be held when the returned revert function is called! 570 // proxyPortsMutex must NOT be held when the returned finalize function is called! 571 func (p *Proxy) removeRedirect(id string, wg *completion.WaitGroup) (err error, finalizeFunc revert.FinalizeFunc, revertFunc revert.RevertFunc) { 572 log.WithField(fieldProxyRedirectID, id). 573 Debug("Removing proxy redirect") 574 575 r, ok := p.redirects[id] 576 if !ok { 577 return fmt.Errorf("unable to find redirect %s", id), nil, nil 578 } 579 delete(p.redirects, id) 580 581 implFinalizeFunc, implRevertFunc := r.implementation.Close(wg) 582 583 // Delay the release and reuse of the port number so it is guaranteed to be 584 // safe to listen on the port again. This can't be reverted, so do it in a 585 // FinalizeFunc. 586 proxyPort := r.listener.proxyPort 587 listenerName := r.listener.name 588 589 finalizeFunc = func() { 590 // break GC loop (implementation may point back to 'r') 591 r.implementation = nil 592 593 if implFinalizeFunc != nil { 594 implFinalizeFunc() 595 } 596 597 go func() { 598 time.Sleep(portReuseDelay) 599 600 proxyPortsMutex.Lock() 601 err := p.releaseProxyPort(listenerName) 602 proxyPortsMutex.Unlock() 603 if err != nil { 604 log.WithField(fieldProxyRedirectID, id).WithError(err).Warningf("Releasing proxy port %d failed", proxyPort) 605 } 606 }() 607 } 608 609 revertFunc = func() error { 610 if implRevertFunc != nil { 611 return implRevertFunc() 612 } 613 614 p.mutex.Lock() 615 p.redirects[id] = r 616 p.mutex.Unlock() 617 618 return nil 619 } 620 621 return 622 } 623 624 // ChangeLogLevel changes proxy log level to correspond to the logrus log level 'level'. 625 func ChangeLogLevel(level logrus.Level) { 626 if envoyProxy != nil { 627 envoyProxy.ChangeLogLevel(level) 628 } 629 } 630 631 // GetStatusModel returns the proxy status as API model 632 func (p *Proxy) GetStatusModel() *models.ProxyStatus { 633 p.mutex.RLock() 634 defer p.mutex.RUnlock() 635 636 return &models.ProxyStatus{ 637 IP: node.GetInternalIPv4().String(), 638 PortRange: fmt.Sprintf("%d-%d", p.rangeMin, p.rangeMax), 639 } 640 } 641 642 // updateRedirectMetrics updates the redirect metrics per application protocol 643 // in Prometheus. Lock needs to be held to call this function. 644 func (p *Proxy) updateRedirectMetrics() { 645 result := map[string]int{} 646 for _, redirect := range p.redirects { 647 result[string(redirect.listener.parserType)]++ 648 } 649 for proto, count := range result { 650 metrics.ProxyRedirects.WithLabelValues(proto).Set(float64(count)) 651 } 652 } 653 654 // FML Added in backport 655 656 // UpdateNetworkPolicy must update the redirect configuration of an endpoint in the proxy 657 func (p *Proxy) UpdateNetworkPolicy(ep logger.EndpointUpdater, policy *policy.L4Policy, ingressPolicyEnforced, egressPolicyEnforced bool, wg *completion.WaitGroup) (error, func() error) { 658 return p.XDSServer.UpdateNetworkPolicy(ep, policy, ingressPolicyEnforced, egressPolicyEnforced, wg) 659 } 660 661 // UseCurrentNetworkPolicy inserts a Completion to the WaitGroup if the current network policy has not yet been acked 662 func (p *Proxy) UseCurrentNetworkPolicy(ep logger.EndpointUpdater, policy *policy.L4Policy, wg *completion.WaitGroup) { 663 p.XDSServer.UseCurrentNetworkPolicy(ep, policy, wg) 664 }