Beispiel #1
0
func floodNodes(actions []nom.Action) (nodes map[nom.UID]nom.UID) {
	fn := make(map[nom.UID]nom.UID)
	for _, a := range actions {
		switch f := a.(type) {
		case nom.ActionFlood:
			nid := nom.NodeFromPortUID(f.InPort)
			fn[nid] = f.InPort
		}
	}
	return fn
}
Beispiel #2
0
func inPortsFromOutPorts(outport []nom.UID, ctx bh.RcvContext) (
	inports []nom.UID) {

nextoutport:
	for _, p := range outport {
		n := nom.NodeFromPortUID(p)
		for _, l := range discovery.LinksCentralized(n, ctx) {
			if l.From == p {
				inports = append(inports, p)
				continue nextoutport
			}
		}
		glog.Errorf("cannot find peer port for %v", p)
	}
	return inports
}
Beispiel #3
0
func genFlowsForPathlet(p nom.Pathlet, inport nom.UID, priority uint16,
	ctx bh.RcvContext) (flows []nom.FlowEntry, outports []nom.UID, err error) {

	fwdnps := forwardNodes(p.Actions)
	for _, ports := range fwdnps {
		outports = append(outports, ports...)
	}
	floodns := floodNodes(p.Actions)
	for n, p := range floodns {
		outports = append(outports, outPortsFromFloodNode(n, p, ctx)...)
	}

	port, matchHasPort := p.Match.InPort()
	if matchHasPort {
		if inport != nom.Nil && inport != nom.UID(port) {
			return nil, nil, fmt.Errorf("path: two different inports %v and %v",
				inport, port)
		}
		inport = nom.UID(port)
	}

	m := p.Match
	if inport != nom.Nil && !matchHasPort {
		m = p.Match.Clone()
		m.Fields = append(m.Fields, nom.InPort(inport))
	}

	noinMatch := p.Match.Clone()
	for f := range m.Fields {
		if _, ok := m.Fields[f].(nom.InPort); ok {
			noinMatch.Fields = append(noinMatch.Fields[:f], m.Fields[f+1:]...)
			break
		}
	}

	nofwdActions := make([]nom.Action, 0, len(p.Actions))
	for _, a := range p.Actions {
		switch a.(type) {
		case nom.ActionForward, nom.ActionFlood:
			continue
		default:
			nofwdActions = append(nofwdActions, a)
		}
	}

	var innodes []nom.UID
	if inport != nom.Nil {
		innodes = []nom.UID{nom.NodeFromPortUID(inport)}
	} else {
		innodes = discovery.NodesCentralized(ctx)
	}

	for _, inn := range innodes {
		for _, outp := range outports {
			outn := nom.NodeFromPortUID(outp)
			sps, l := discovery.ShortestPathCentralized(inn, outn, ctx)
			if l < 0 {
				// TODO(soheil): maybe just log this and continue installing other
				// flows.
				return nil, nil, fmt.Errorf("path: no path found from %v to %v", inport,
					outp)
			}

			if l == 0 {
				m := noinMatch.Clone()
				if inport != nom.Nil {
					m.Fields = append(m.Fields, nom.InPort(inport))
				}
				flow := nom.FlowEntry{
					Node:     outn,
					Match:    m,
					Actions:  p.Actions,
					Priority: priority,
				}
				flows = append(flows, flow)
				continue
			}

			// TODO(soheil): maybe install multiple paths.
			lastInPort := inport
			for _, link := range sps[0] {
				m := noinMatch.Clone()
				if lastInPort != nom.Nil {
					m.Fields = append(m.Fields, nom.InPort(lastInPort))
				}

				var a []nom.Action
				a = append(a, nofwdActions...)
				a = append(a, nom.ActionForward{Ports: []nom.UID{link.From}})

				flow := nom.FlowEntry{
					Node:     nom.NodeFromPortUID(link.From),
					Match:    m,
					Actions:  a,
					Priority: priority,
				}
				flows = append(flows, flow)

				lastInPort = link.To
			}

			m := noinMatch.Clone()
			if lastInPort != nom.Nil {
				m.Fields = append(m.Fields, nom.InPort(lastInPort))
			}
			flow := nom.FlowEntry{
				Node:     outn,
				Match:    m,
				Actions:  p.Actions,
				Priority: priority,
			}
			flows = append(flows, flow)
		}
	}
	return flows, outports, nil
}