Example #1
0
func (b GraphBuilderCentralized) Rcv(msg bh.Msg, ctx bh.RcvContext) error {
	dict := ctx.Dict(GraphDict)
	var link nom.Link
	switch dm := msg.Data().(type) {
	case nom.LinkAdded:
		link = nom.Link(dm)
	case nom.LinkDeleted:
		link = nom.Link(dm)
	default:
		return fmt.Errorf("GraphBuilderCentralized: unsupported message type %v",
			msg.Type())
	}

	nf, _ := nom.ParsePortUID(link.From)
	nt, _ := nom.ParsePortUID(link.To)

	if nf == nt {
		return fmt.Errorf("%v is a loop", link)
	}

	k := string(nf)
	links := make(map[nom.UID][]nom.Link)
	if v, err := dict.Get(k); err == nil {
		links = v.(map[nom.UID][]nom.Link)
	}
	links[nt.UID()] = append(links[nt.UID()], link)
	return dict.Put(k, links)
}
Example #2
0
func decodeLLDP(b []byte) (nom.Node, nom.Port, error) {
	h := lldp.NewLinkDiscoveryProtocolWithBuf(b)
	size := h.Size()

	tlvb := b[size:]
	chTLV := lldp.NewChassisMacTLVWithBuf(tlvb)
	if chTLV.Size() == 0 {
		return nom.Node{}, nom.Port{}, errors.New("decodeLLDP: no chassis id")
	}
	n := nom.Node{
		MACAddr: chTLV.MacAddr(),
	}
	size += chTLV.Size()

	tlvb = b[size:]
	pTLV := lldp.NewLinkDiscoveryTLVWithBuf(tlvb)
	if pTLV.Size() == 0 || pTLV.Type() != uint8(lldp.TLV_PORT_ID) {
		return nom.Node{}, nom.Port{}, errors.New("decodeLLDP: no port id")
	}

	v := pTLV.Value()
	if v[0] != uint8(lldp.PORT_TLV_IFACE_NAME) {
		return nom.Node{}, nom.Port{}, errors.New("decodeLLDP: no port iface name")
	}

	portUID := nom.UID(v[1:])
	nID, pID := nom.ParsePortUID(portUID)
	n.ID = nID

	return n, nom.Port{ID: pID, Node: n.UID()}, nil
}
Example #3
0
func allPaths(from, to nom.UID, visited map[nom.UID]distAndLinks) (
	[][]nom.Link, int) {

	if from == to {
		return nil, 0
	}

	todl, ok := visited[to]
	if !ok {
		return nil, -1
	}

	var paths [][]nom.Link
	for _, l := range todl.BackLinks {
		lfn, _ := nom.ParsePortUID(l.From)
		prevpaths, _ := allPaths(from, nom.UID(lfn), visited)
		if len(prevpaths) == 0 {
			paths = append(paths, []nom.Link{l})
			continue
		}
		for _, p := range prevpaths {
			paths = append(paths, append(p, l))
		}
	}
	return paths, todl.Dist
}
Example #4
0
// ShortestPathCentralized calculates the shortest path from node "from" to node
// "to" according to the state stored in GraphDict by the
// GraphBuilderCentralized.
//
// This method is not go-routine safe and must be called within a handler of the
// application that uses the GraphBuilderCentralized as a handler. Otherwise,
// the user needs to synchronize the two.
func ShortestPathCentralized(from, to nom.UID, ctx bh.RcvContext) (
	paths [][]nom.Link, length int) {

	if from == to {
		return nil, 0
	}

	visited := make(map[nom.UID]distAndLinks)
	visited[from] = distAndLinks{Dist: 0}

	pq := nodeAndDistSlice{{Dist: 0, Node: from}}
	heap.Init(&pq)

	dict := ctx.Dict(GraphDict)
	for len(pq) != 0 {
		nd := heap.Pop(&pq).(nodeAndDist)
		if nd.Node == to {
			continue
		}
		nodeLinks := make(map[nom.UID][]nom.Link)
		if v, err := dict.Get(string(nd.Node)); err == nil {
			nodeLinks = v.(map[nom.UID][]nom.Link)
		}
		nd.Dist = visited[nd.Node].Dist
		for _, links := range nodeLinks {
			for _, l := range links {
				nid, _ := nom.ParsePortUID(l.To)
				ton := nom.UID(nid)
				if dl, ok := visited[ton]; ok {
					switch {
					case nd.Dist+1 < dl.Dist:
						glog.Fatalf("invalid distance in BFS")
					case nd.Dist+1 == dl.Dist:
						dl.BackLinks = append(dl.BackLinks, l)
						visited[ton] = dl
					}
					continue
				}

				visited[ton] = distAndLinks{
					Dist:      nd.Dist + 1,
					BackLinks: []nom.Link{l},
				}
				ndto := nodeAndDist{
					Dist: nd.Dist + 1,
					Node: ton,
				}
				heap.Push(&pq, ndto)
			}
		}
	}
	return allPaths(from, to, visited)
}
Example #5
0
func forwardNodes(actions []nom.Action) (nodeToPorts map[nom.UID][]nom.UID) {
	nodeToPorts = make(map[nom.UID][]nom.UID)
	for _, a := range actions {
		switch f := a.(type) {
		case nom.ActionForward:
			for _, p := range f.Ports {
				fnid, _ := nom.ParsePortUID(p)
				ports := nodeToPorts[fnid.UID()]
				ports = append(ports, p)
				nodeToPorts[fnid.UID()] = ports
			}
		}
	}
	return nodeToPorts
}
Example #6
0
func (b GraphBuilderCentralized) Map(msg bh.Msg,
	ctx bh.MapContext) bh.MappedCells {

	var from nom.UID
	switch dm := msg.Data().(type) {
	case nom.LinkAdded:
		from = dm.From
	case nom.LinkDeleted:
		from = dm.From
	default:
		return nil
	}
	// TODO(soheil): maybe store and update the matrix directly here.
	n, _ := nom.ParsePortUID(from)
	return bh.MappedCells{{GraphDict, string(n)}}
}
Example #7
0
func (h *newLinkHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error {
	l := nom.Link(msg.Data().(NewLink))
	n, _ := nom.ParsePortUID(l.From)
	d := ctx.Dict(nodeDict)
	k := string(n)
	v, err := d.Get(k)
	if err != nil {
		return err
	}
	np := v.(nodePortsAndLinks)

	if oldl, ok := np.linkFrom(l.From); ok {
		if oldl.UID() == l.UID() {
			return nil
		}
		np.removeLink(oldl)
		ctx.Emit(nom.LinkDeleted(oldl))
	}

	glog.V(2).Infof("Link detected %v", l)
	ctx.Emit(nom.LinkAdded(l))
	np.L = append(np.L, l)
	return d.Put(k, np)
}
Example #8
0
func (h *newLinkHandler) Map(msg bh.Msg, ctx bh.MapContext) bh.MappedCells {
	n, _ := nom.ParsePortUID(msg.Data().(NewLink).From)
	return bh.MappedCells{{nodeDict, string(n)}}
}