Ejemplo n.º 1
0
// 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) {
		}
	}
}
Ejemplo n.º 2
0
func (h *Renderer) Provision(g canvas.Graph, nodes []InterfaceNode) (err error) {
	newIds := []canvas.NodeIfc{}
	visitFn := func(prev, this canvas.Node) {
		provisionNode(g, this, &newIds)
	}
	t := canvas.NewDepthFirst(visitFn, filterInterfaceNode)

	defer func() {
		if r := recover(); r != nil {
			switch r := r.(type) {
			case error:
				err = r
				for _, ni := range newIds {
					g.Node(ni.ID()).ReleaseInterfaceID(ni.Ifc())
				}
				// rollback
			default:
				panic(r)
			}
		}
	}()

	// Find all of the Adapter (internal) nodes reachable from an external interface.
	// Collect the ID of each node and update the modules table.
	for _, node := range nodes {
		if node.ID() < 0 {
			continue
		}
		provisionNode(g, node, &newIds)
		t.Walk(g, node, nil)
	}
	return
}
Ejemplo n.º 3
0
func (nm *NetlinkMonitor) ensureInterface(g canvas.Graph, node InterfaceNode) error {
	if node.ID() < 0 {
		return nil
	}
	Info.Printf("visit: id=%d :: fd=%d :: %s :: %d\n", node.ID(), node.FD(), node.Path(), node.Link().Attrs().Index)
	nm.modules.Set(strconv.Itoa(node.ID()), strconv.Itoa(node.FD()))
	switch deg := g.Degree(node); deg {
	case 2:
		//Debug.Printf("Adding ingress for %s\n", node.Link().Attrs().Name)
		next := g.From(node)[0].(canvas.Node)
		e := g.E(node, next)
		if e.Serialize()[0] == 0 {
			return nil
		}
		chain, err := NewIngressChain(e.Serialize())
		if err != nil {
			return err
		}
		defer chain.Close()
		Info.Printf(" %4d: %-11s%s\n", e.F().Ifc(), next.Path(), e)
		if err := ensureIngressFd(node.Link(), chain.FD()); err != nil {
			return err
		}
	default:
		return fmt.Errorf("Invalid # edges for node %s, must be 2, got %d", node.Path(), deg)
	}
	return nil
}
Ejemplo n.º 4
0
func (h *Renderer) Run(g canvas.Graph, nodes []InterfaceNode) {
	visitFn := func(prev, this canvas.Node) {
		Info.Printf("visit: %d :: %s\n", this.ID(), this.Path())
		for _, t := range g.From(this) {
			e := g.E(this, t)
			adapter := this.(*canvas.AdapterNode).Adapter()
			if e.IsDeleted() {
				fc := adapter.Table("forward_chain")
				if fc == nil {
					panic(fmt.Errorf("Could not find forward_chain in adapter"))
				}

				// find and delete the reverse edge as well
				e2 := g.E(t, this)
				if !e2.IsDeleted() {
					panic(fmt.Errorf("Reverse edge %d->%d is not deleted", t.ID(), this.ID()))
				}

				// clear previous entry (if any) in the ifc table
				key := fmt.Sprintf("%d", e.F().Ifc())
				if err := fc.Set(key, "{ [ 0x0 0x0 0x0 0x0 ] }"); err != nil {
					panic(err)
				}

				g.RemoveEdge(e)
				g.RemoveEdge(e2)

				// do not perform any further processing on node 't'
				continue
			}
			target := t.(canvas.Node)
			if adapter.Type() == "bridge" {
				if target, ok := target.(*ExtInterface); ok {
					if e.Serialize()[0] == 0 {
						continue
					}
					chain, err := NewEgressChain(e.Serialize())
					if err != nil {
						panic(err)
					}
					defer chain.Close()
					Info.Printf(" %4d: %-11s%s\n", e.F().Ifc(), target.Path(), e)
					if err := ensureEgressFd(target.Link(), chain.FD()); err != nil {
						panic(err)
					}
				}
			} else {
				fc := adapter.Table("forward_chain")
				if fc == nil {
					panic(fmt.Errorf("Could not find forward_chain in adapter"))
				}
				key := fmt.Sprintf("%d", e.F().Ifc())
				val := fmt.Sprintf("{%#x}", e.Serialize())
				Info.Printf(" %4s: %-11s%s\n", key, target.Path(), val)
				if err := fc.Set(key, val); err != nil {
					panic(err)
				}
				//Debug.Printf(" %s:%d -> %s:%d\n", this.Path(), i, target.Path(), target.ID())
			}
		}
	}
	t := canvas.NewDepthFirst(visitFn, filterInterfaceNode)
	// Find all of the Adapter (internal) nodes reachable from an external interface.
	// Collect the ID of each node and update the modules table.
	for _, node := range nodes {
		if node.ID() < 0 {
			continue
		}
		t.Walk(g, node, nil)
	}

	// reset interfaces with degree 0; these interfaces are now unreachable
	for _, node := range nodes {
		//Debug.Printf("Run cleanup: considering node %d\n", node.ID())
		if node.ID() < 0 {
			continue
		}
		degree := g.Degree(node)
		//Debug.Printf("Run cleanup: node %d has degree %d\n", node.ID(), degree)
		if degree != 0 {
			continue
		}
		g.RemoveNode(node)

		// release and reset ID allocated for this interface
		node.ReleaseInterfaceID(node.ID())
		node.SetID(-1)
	}

}