// provisionNode allocates the IDs for one node, meant to be called from a tree // traversal. If allocation fails, panic and expect to be recovered. The // allocated IDs are stored in newIds so as to be collected in the recover // routine. func provisionNode(g canvas.Graph, this canvas.Node, newIds *[]canvas.NodeIfc) { Info.Printf("Provisioning %s (%d)\n", this, this.ID()) for _, t := range g.From(this) { e := g.E(this, t) target := t.(canvas.Node) chain := computeChainFrom(this, target) fid, tid := e.F().Ifc(), e.T().Ifc() var err error if fid < 0 { if fid, err = e.From().(canvas.Node).NewInterfaceID(); err != nil { Error.Printf("Provisioning %s failed %s\n", e.From().(canvas.Node), err) panic(err) } *newIds = append(*newIds, canvas.NodeIfc{e.From().ID(), fid}) } if tid < 0 { if tid, err = e.To().(canvas.Node).NewInterfaceID(); err != nil { Error.Printf("Provisioning %s failed %s\n", e.To().(canvas.Node), err) panic(err) } *newIds = append(*newIds, canvas.NodeIfc{e.To().ID(), tid}) } if e.Update(chain, fid, tid) { } } }
func computeChainFrom(from, to canvas.Node) (chain []canvas.NodeIfc) { // For each link, there is a chain of modules to be invoked: the // ingress policy modules, the egress policy modules, and the final // forwarding nexthop. // // To compute the chain in each direction, the following algorithm is // followed: // Let T and F represent the set of groups for the 'to' and 'from' // nodes, respectively. // The leaving set L is the set difference between F and T. // L := F - T // The entering set E is the set difference between T and F // E := T - F // // For the directed edge from:to, the chain is built as follows: // For each module e in E, invoke the ingress policy (e.ifc[1]) // For each module l in L, invoke the egress policy (l.ifc[2]) // // The directed edge to:from is calculated by calling this function // with to/from reversed. var e, l, x intsets.Sparse l.Difference(from.Groups(), to.Groups()) e.Difference(to.Groups(), from.Groups()) var id int x.Copy(&e) for x.TakeMin(&id) { chain = append(chain, canvas.NodeIfc{id, 1}) } x.Copy(&l) for x.TakeMin(&id) { chain = append(chain, canvas.NodeIfc{id, 2}) } return chain }