Пример #1
0
func TestAddP2PPath(t *testing.T) {
	ctx := buildTopologyForTest()
	p := addHandler{}
	msg := &bh.MockMsg{
		MsgData: nom.AddPath{},
	}
	err := p.Rcv(msg, ctx)
	if err == nil {
		t.Error("no error on invalid path")
	}
	msg.MsgData = nom.AddPath{
		Path: nom.Path{
			Pathlets: []nom.Pathlet{
				{
					Match: nom.Match{
						Fields: []nom.Field{
							nom.InPort("n1$$0"),
						},
					},
					Actions: []nom.Action{
						nom.ActionForward{
							Ports: []nom.UID{"n6$$3"},
						},
					},
				},
			},
			Priority: 1,
		},
	}
	if err := p.Rcv(msg, ctx); err != nil {
		t.Errorf("cannot install flows for path: %v", err)
	}
	if len(ctx.CtxMsgs) == 0 {
		t.Error("no flows installed")
	}

	iports := []nom.UID{"n1$$0", "n2$$1", "n4$$1", "n6$$1"}
	oports := []nom.UID{"n1$$1", "n2$$2", "n4$$2", "n6$$3"}
	for i, msg := range ctx.CtxMsgs {
		add := msg.Data().(nom.AddFlowEntry)
		if add.Flow.Priority != 1 {
			t.Errorf("invalid flow priority: actual=%v want=1", add.Flow.Priority)
		}
		iport, ok := add.Flow.Match.InPort()
		if !ok {
			t.Errorf("flow #%v has no in ports", i)
		} else if nom.UID(iport) != iports[i] {
			t.Errorf("invalid input port on flow #%v: actual=%v want=%v", i, iport,
				iports[i])
		}

		oport := add.Flow.Actions[0].(nom.ActionForward).Ports[0]
		if oport != oports[i] {
			t.Errorf("invalid output port on flow #%v: actual=%v want=%v", i, oport,
				oports[i])
		}
	}
}
Пример #2
0
func (d *of10Driver) nomMatch(m of10.Match) (nom.Match, error) {
	nm := nom.Match{}
	wc := of10.FlowWildcards(m.Wildcards())
	if wc&of10.PFW_IN_PORT == 0 {
		ofp := m.InPort()
		nomp, ok := d.ofPorts[ofp]
		if !ok {
			return nom.Match{}, fmt.Errorf("of10Driver: cannot find port %v", ofp)
		}
		nm.AddField(nom.InPort(nomp.UID()))
	}
	if wc&of10.PFW_DL_SRC == 0 {
		nm.AddField(nom.EthSrc{
			Addr: m.DlSrc(),
			Mask: nom.MaskNoneMAC,
		})
	}
	if wc&of10.PFW_DL_DST == 0 {
		nm.AddField(nom.EthDst{
			Addr: m.DlDst(),
			Mask: nom.MaskNoneMAC,
		})
	}
	if wc&of10.PFW_DL_TYPE == 0 {
		nm.AddField(nom.EthType(m.DlType()))
	}
	if wc&of10.PFW_NW_SRC_MASK != of10.PFW_NW_SRC_ALL && m.NwSrc() != 0 {
		mask := uint(wc&of10.PFW_NW_SRC_MASK) >> uint(of10.PFW_NW_SRC_SHIFT)
		nm.AddField(nom.IPv4Src(nom.CIDRToMaskedIPv4(m.NwSrc(), mask)))
	}
	if wc&of10.PFW_NW_DST_MASK != of10.PFW_NW_DST_ALL && m.NwDst() != 0 {
		mask := uint(wc&of10.PFW_NW_DST_MASK) >> uint(of10.PFW_NW_DST_SHIFT)
		nm.AddField(nom.IPv4Dst(nom.CIDRToMaskedIPv4(m.NwDst(), mask)))
	}
	if wc&of10.PFW_TP_SRC == 0 {
		nm.AddField(nom.TransportPortSrc(m.TpSrc()))
	}
	if wc&of10.PFW_TP_DST == 0 {
		nm.AddField(nom.TransportPortDst(m.TpDst()))
	}
	return nm, nil
}
Пример #3
0
func (d *of12Driver) nomMatch(m of12.Match) (nom.Match, error) {
	nm := nom.Match{}

	if !of12.IsOXMatch(m) {
		return nm, fmt.Errorf("of12Driver: std math is not supported")
	}

	xm, err := of12.ToOXMatch(m)
	if err != nil {
		return nm, err
	}

	for _, f := range xm.Fields() {
		switch f.OxmField() {
		case uint8(of12.PXMT_IN_PORT):
			xf, err := of12.ToOxmInPort(f)
			if err != nil {
				return nom.Match{}, err
			}

			np, ok := d.ofPorts[xf.InPort()]
			if !ok {
				return nom.Match{}, fmt.Errorf("of12Driver: cannot find port %v",
					xf.InPort())
			}
			nm.AddField(nom.InPort(np.UID()))

		case uint8(of12.PXMT_ETH_TYPE):
			xf, err := of12.ToOxmEthType(f)
			if err != nil {
				return nom.Match{}, err
			}
			nm.AddField(nom.EthType(xf.Type()))

		case uint8(of12.PXMT_ETH_SRC):
			xf, err := of12.ToOxmEthSrc(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.EthSrc{}
			nf.Addr = xf.MacAddr()
			nf.Mask = nom.MaskNoneMAC
			nm.AddField(nf)

		case uint8(of12.PXMT_ETH_SRC_MASKED):
			xf, err := of12.ToOxmEthSrcMasked(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.EthSrc{}
			nf.Addr = xf.MacAddr()
			nf.Mask = xf.Mask()
			nm.AddField(nf)

		case uint8(of12.PXMT_ETH_DST):
			xf, err := of12.ToOxmEthDst(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.EthDst{}
			nf.Addr = xf.MacAddr()
			nf.Mask = nom.MaskNoneMAC
			nm.AddField(nf)

		case uint8(of12.PXMT_ETH_DST_MASKED):
			xf, err := of12.ToOxmEthDstMasked(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.EthDst{}
			nf.Addr = xf.MacAddr()
			nf.Mask = xf.Mask()
			nm.AddField(nf)

		case uint8(of12.PXMT_IP_PROTO):
			xf, err := of12.ToOxmIpProto(f)
			if err != nil {
				return nom.Match{}, err
			}

			nm.AddField(nom.IPProto(xf.Proto()))

		case uint8(of12.PXMT_IPV4_SRC):
			xf, err := of12.ToOxmIpV4Src(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.IPv4Src{}
			nf.Addr = nom.IPv4Addr(xf.Addr())
			nf.Mask = nom.MaskNoneIPV4
			nm.AddField(nf)

		case uint8(of12.PXMT_IPV4_SRC_MASKED):
			xf, err := of12.ToOxmIpV4SrcMasked(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.IPv4Src{}
			nf.Addr = nom.IPv4Addr(xf.Addr())
			nf.Mask = nom.IPv4Addr(xf.Mask())
			nm.AddField(nf)

		case uint8(of12.PXMT_IPV4_DST):
			xf, err := of12.ToOxmIpV4Dst(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.IPv4Dst{}
			nf.Addr = nom.IPv4Addr(xf.Addr())
			nf.Mask = nom.MaskNoneIPV4
			nm.AddField(nf)

		case uint8(of12.PXMT_IPV4_DST_MASKED):
			xf, err := of12.ToOxmIpV4DstMasked(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.IPv4Dst{}
			nf.Addr = nom.IPv4Addr(xf.Addr())
			nf.Mask = nom.IPv4Addr(xf.Mask())
			nm.AddField(nf)

		case uint8(of12.PXMT_IPV6_SRC):
			xf, err := of12.ToOxmIpV6Src(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.IPv6Src{}
			nf.Addr = nom.IPv6Addr(xf.Addr())
			nf.Mask = nom.MaskNoneIPV6
			nm.AddField(nf)

		case uint8(of12.PXMT_IPV6_SRC_MASKED):
			xf, err := of12.ToOxmIpV6SrcMasked(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.IPv6Src{}
			nf.Addr = nom.IPv6Addr(xf.Addr())
			nf.Mask = nom.IPv6Addr(xf.Mask())
			nm.AddField(nf)

		case uint8(of12.PXMT_IPV6_DST):
			xf, err := of12.ToOxmIpV6Dst(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.IPv6Dst{}
			nf.Addr = nom.IPv6Addr(xf.Addr())
			nf.Mask = nom.MaskNoneIPV6
			nm.AddField(nf)

		case uint8(of12.PXMT_IPV6_DST_MASKED):
			xf, err := of12.ToOxmIpV6DstMasked(f)
			if err != nil {
				return nom.Match{}, err
			}

			nf := nom.IPv6Dst{}
			nf.Addr = nom.IPv6Addr(xf.Addr())
			nf.Mask = nom.IPv6Addr(xf.Mask())
			nm.AddField(nf)

		case uint8(of12.PXMT_TCP_SRC):
			xf, err := of12.ToOxmTcpSrc(f)
			if err != nil {
				return nom.Match{}, err
			}

			nm.AddField(nom.TransportPortSrc(xf.Port()))

		case uint8(of12.PXMT_TCP_DST):
			xf, err := of12.ToOxmTcpDst(f)
			if err != nil {
				return nom.Match{}, err
			}

			nm.AddField(nom.TransportPortDst(xf.Port()))
		}
	}

	return nm, nil
}
Пример #4
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
}