Example #1
0
func (fastdp *FastDatapath) makeBridgeVport(vport odp.Vport) {
	// Set up a bridge port for netdev and internal vports.  vxlan
	// vports are handled separately, as they do not correspond to
	// bridge ports (we set up the miss handler for them in
	// getVxlanVportID).
	typ := vport.Spec.TypeName()
	if typ != "netdev" && typ != "internal" {
		return
	}

	vportID := vport.ID

	// Sending to the bridge port outputs on the vport:
	fastdp.addSendToPort(bridgePortID{vport: vportID},
		func(_ PacketKey, _ *fastDatapathLock) FlowOp {
			return fastdp.odpActions(odp.NewOutputAction(vportID))
		})

	// Delete flows, in order to recalculate flows for broadcasts
	// on the bridge.
	checkWarn(fastdp.deleteFlows())

	// Packets coming from the netdev are processed by the bridge
	fastdp.missHandlers[vportID] = func(flowKeys odp.FlowKeys, lock *fastDatapathLock) FlowOp {
		return fastdp.bridge(bridgePortID{vport: vportID}, flowKeysToPacketKey(flowKeys), lock)
	}
}
Example #2
0
func (fwd *fastDatapathForwarder) Forward(key ForwardPacketKey) FlowOp {
	if !key.SrcPeer.HasShortID || !key.DstPeer.HasShortID {
		return nil
	}

	fwd.lock.RLock()
	defer fwd.lock.RUnlock()

	if fwd.remoteAddr == nil {
		// Returning nil would discard the packet, but also
		// result in a flow rule, which we would have to
		// invalidate when we learn the remote IP.  So for
		// now, just prevent flows.
		return vetoFlowCreationFlowOp{}
	}

	remoteIP, err := ipv4Bytes(fwd.remoteAddr.IP)
	if err != nil {
		log.Error(err)
		return DiscardingFlowOp{}
	}

	var sta odp.SetTunnelAction
	sta.SetTunnelId(tunnelIDFor(key))
	sta.SetIpv4Src(fwd.localIP)
	sta.SetIpv4Dst(remoteIP)
	sta.SetTos(0)
	sta.SetTtl(64)
	sta.SetDf(true)
	sta.SetCsum(false)
	return fwd.fastdp.odpActions(sta, odp.NewOutputAction(fwd.vxlanVportID))
}
Example #3
0
File: main.go Project: awh/go-odp
func flagsToFlowSpec(f Flags, dpif *odp.Dpif) (dp odp.DatapathHandle, flow odp.FlowSpec, ok bool) {
	flow = odp.NewFlowSpec()

	var inPort string
	f.StringVar(&inPort, "in-port", "", "key: incoming vport")

	var ethSrc, ethDst string
	f.StringVar(&ethSrc, "eth-src", "", "key: ethernet source MAC")
	f.StringVar(&ethDst, "eth-dst", "", "key: ethernet destination MAC")

	var tun tunnelFlags
	addTunnelFlags(f, &tun, "tunnel-", "tunnel ")

	var setTun tunnelFlags
	addTunnelFlags(f, &setTun, "set-tunnel-", "action: set tunnel ")

	var output string
	f.StringVar(&output, "output", "", "action: output to vports")

	args := f.Parse(1, 1)
	dpp, _ := lookupDatapath(dpif, args[0])
	if dpp == nil {
		return
	}

	if inPort != "" {
		vport, err := dpp.LookupVportByName(inPort)
		if err != nil {
			printErr("%s", err)
			return
		}
		flow.AddKey(odp.NewInPortFlowKey(vport.ID))
	}

	// The ethernet flow key is mandatory
	err := handleEthernetFlowKeyOptions(flow, ethSrc, ethDst)
	if err != nil {
		printErr("%s", err)
		return
	}

	flowKey, err := parseTunnelFlags(&tun)
	if err != nil {
		printErr("%s", err)
		return
	}

	if !flowKey.Ignored() {
		flow.AddKey(flowKey)
	}

	// Actions are ordered, but flags aren't.  As a temporary
	// hack, we already put SET actions before an OUTPUT action.

	setTunAttrs, err := parseSetTunnelFlags(&setTun)
	if err != nil {
		printErr("%s", err)
		return
	}

	if setTunAttrs != nil {
		flow.AddAction(*setTunAttrs)
	}

	if output != "" {
		for _, vpname := range strings.Split(output, ",") {
			vport, err := dpp.LookupVportByName(vpname)
			if err != nil {
				printErr("%s", err)
				return
			}
			flow.AddAction(odp.NewOutputAction(vport.ID))
		}
	}

	return *dpp, flow, true
}