Merge pull request openziti/fabric#430 from openziti/prevent-strange-loops

Prevent strange loops
This commit is contained in:
Paul Lorenz
2022-07-01 15:37:59 -04:00
committed by GitHub
12 changed files with 104 additions and 37 deletions
+4
View File
@@ -17,6 +17,7 @@
package api_impl
import (
"github.com/go-openapi/strfmt"
"github.com/openziti/fabric/controller/api"
"github.com/openziti/fabric/controller/network"
@@ -52,12 +53,15 @@ func MapCircuitToRestModel(_ *network.Network, _ api.RequestContext, circuit *ne
for _, link := range circuit.Path.Links {
path.Links = append(path.Links, ToEntityRef(link.Id, link, LinkLinkFactory))
}
createdAt := strfmt.DateTime(circuit.CreatedAt)
ret := &rest_model.CircuitDetail{
ID: &circuit.Id,
ClientID: circuit.ClientId,
Path: path,
Service: ToEntityRef(circuit.Service.Name, circuit.Service, ServiceLinkFactory),
Terminator: ToEntityRef(circuit.Terminator.GetId(), circuit.Terminator, TerminatorLinkFactory),
CreatedAt: &createdAt,
}
return ret, nil
+12 -10
View File
@@ -21,6 +21,7 @@ import (
"github.com/openziti/fabric/controller/xt"
"github.com/openziti/foundation/v2/concurrenz"
"github.com/orcaman/concurrent-map/v2"
"time"
)
type Circuit struct {
@@ -31,6 +32,7 @@ type Circuit struct {
Path *Path
Rerouting concurrenz.AtomicBoolean
PeerData xt.PeerData
CreatedAt time.Time
}
func (self *Circuit) cost() int64 {
@@ -68,29 +70,29 @@ func newCircuitController() *circuitController {
}
}
func (c *circuitController) nextCircuitId() (string, error) {
return c.idGenerator.NextAlphaNumericPrefixedId()
func (self *circuitController) nextCircuitId() (string, error) {
return self.idGenerator.NextAlphaNumericPrefixedId()
}
func (c *circuitController) add(sn *Circuit) {
c.circuits.Set(sn.Id, sn)
func (self *circuitController) add(circuit *Circuit) {
self.circuits.Set(circuit.Id, circuit)
}
func (c *circuitController) get(id string) (*Circuit, bool) {
if circuit, found := c.circuits.Get(id); found {
func (self *circuitController) get(id string) (*Circuit, bool) {
if circuit, found := self.circuits.Get(id); found {
return circuit, true
}
return nil, false
}
func (c *circuitController) all() []*Circuit {
func (self *circuitController) all() []*Circuit {
circuits := make([]*Circuit, 0)
for tuple := range c.circuits.IterBuffered() {
for tuple := range self.circuits.IterBuffered() {
circuits = append(circuits, tuple.Val)
}
return circuits
}
func (c *circuitController) remove(sn *Circuit) {
c.circuits.Remove(sn.Id)
func (self *circuitController) remove(circuit *Circuit) {
self.circuits.Remove(circuit.Id)
}
+34 -13
View File
@@ -524,6 +524,7 @@ func (network *Network) CreateCircuit(srcR *Router, clientId *identity.TokenId,
Path: path,
Terminator: terminator,
PeerData: peerData,
CreatedAt: time.Now(),
}
network.circuitController.add(circuit)
creationTimespan := time.Since(startTime)
@@ -870,6 +871,24 @@ func (network *Network) rerouteLink(l *Link, deadline time.Time) error {
return nil
}
func (network *Network) rerouteCircuitWithTries(circuit *Circuit, retries int) {
log := pfxlog.Logger().WithField("circuitId", circuit.Id)
for i := 0; i < retries; i++ {
deadline := time.Now().Add(DefaultNetworkOptionsRouteTimeout)
err := network.rerouteCircuit(circuit, deadline)
if err == nil {
return
}
log.WithError(err).WithField("attempt", i).Error("error re-routing circuit")
}
if err := network.RemoveCircuit(circuit.Id, true); err != nil {
log.WithError(err).Error("failure while removing circuit after failed re-route attempt")
}
}
func (network *Network) rerouteCircuit(circuit *Circuit, deadline time.Time) error {
log := pfxlog.Logger().WithField("circuitId", circuit.Id)
if circuit.Rerouting.CompareAndSwap(false, true) {
@@ -901,28 +920,30 @@ func (network *Network) rerouteCircuit(circuit *Circuit, deadline time.Time) err
}
}
func (network *Network) smartReroute(s *Circuit, cq *Path, deadline time.Time) error {
if s.Rerouting.CompareAndSwap(false, true) {
defer s.Rerouting.Set(false)
func (network *Network) smartReroute(circuit *Circuit, cq *Path, deadline time.Time) bool {
retry := false
log := pfxlog.Logger().WithField("circuitId", circuit.Id)
if circuit.Rerouting.CompareAndSwap(false, true) {
defer circuit.Rerouting.Set(false)
s.Path = cq
circuit.Path = cq
rms := cq.CreateRouteMessages(SmartRerouteAttempt, s.Id, s.Terminator, deadline)
rms := cq.CreateRouteMessages(SmartRerouteAttempt, circuit.Id, circuit.Terminator, deadline)
for i := 0; i < len(cq.Nodes); i++ {
if _, err := sendRoute(cq.Nodes[i], rms[i], network.options.RouteTimeout); err != nil {
logrus.Errorf("error sending route to [r/%s] (%s)", cq.Nodes[i].Id, err)
retry = true
log.WithField("routerId", cq.Nodes[i].Id).WithError(err).Error("error sending smart route update to router")
break
}
}
logrus.Debugf("rerouted circuit [s/%s]", s.Id)
network.CircuitEvent(CircuitUpdated, s, nil, nil)
return nil
} else {
logrus.Infof("not rerouting [s/%s], already in progress", s.Id)
return nil
if !retry {
logrus.Debug("rerouted circuit")
network.CircuitEvent(CircuitUpdated, circuit, nil, nil)
}
}
return retry
}
func (network *Network) AcceptMetrics(metrics *metrics_pb.MetricsMessage) {
+2 -2
View File
@@ -85,8 +85,8 @@ func (network *Network) smart() {
* Reroute.
*/
for _, circuit := range candidates {
if err := network.smartReroute(circuit, newPaths[circuit], time.Now().Add(DefaultNetworkOptionsRouteTimeout)); err != nil {
log.Errorf("error rerouting [s/%s] (%s)", circuit.Id, err)
if retry := network.smartReroute(circuit, newPaths[circuit], time.Now().Add(DefaultNetworkOptionsRouteTimeout)); retry {
go network.rerouteCircuitWithTries(circuit, DefaultNetworkOptionsCreateCircuitRetries)
}
}
/* */