Example #1
0
File: main.go Project: awh/go-odp
func listVports(f Flags) bool {
	args := f.Parse(0, 1)

	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	if len(args) == 0 {
		// Although vport names are global, rather than being
		// scoped to a datapath, odp can only enumerate the
		// vports within a datapath.  So enumerating them all
		// is a bit of a faff.
		dps, err := dpif.EnumerateDatapaths()
		if err != nil {
			return printErr("%s", err)
		}

		for dpname, dp := range dps {
			if !printVports(dpname, dp) {
				return false
			}
		}

		return true
	} else {
		dp, dpname := lookupDatapath(dpif, args[0])
		if dp == nil {
			return false
		}

		return printVports(dpname, *dp)
	}
}
Example #2
0
File: main.go Project: awh/go-odp
func deleteVport(f Flags) bool {
	args := f.Parse(1, 1)

	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	dp, vport, err := dpif.LookupVportByName(args[0])
	if err != nil {
		if odp.IsNoSuchVportError(err) {
			return printErr("Cannot find port \"%s\"", args[0])
		}

		return printErr("%s", err)
	}

	err = dp.DeleteVport(vport.ID)
	if err != nil {
		return printErr("%s", err)
	}

	return true
}
Example #3
0
func CreateDatapath(dpname string) error {
	dpif, err := odp.NewDpif()
	if err != nil {
		return err
	}

	defer dpif.Close()

	_, err = dpif.CreateDatapath(dpname)
	if err != nil && !odp.IsDatapathNameAlreadyExistsError(err) {
		return err
	}

	return nil
}
Example #4
0
func AddDatapathInterface(dpname string, ifname string) error {
	dpif, err := odp.NewDpif()
	if err != nil {
		return err
	}
	defer dpif.Close()

	dp, err := dpif.LookupDatapath(dpname)
	if err != nil {
		return err
	}

	_, err = dp.CreateVport(odp.NewNetdevVportSpec(ifname))
	return err
}
Example #5
0
File: main.go Project: awh/go-odp
func listDatapaths(f Flags) bool {
	f.Parse(0, 0)

	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	dps, err := dpif.EnumerateDatapaths()
	for name, dp := range dps {
		fmt.Printf("%d: %s\n", dp.IfIndex(), name)
	}

	return true
}
Example #6
0
func listenForVports(f Flags) bool {
	f.Parse(0, 0)

	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	done := make(chan struct{})
	if err := dpif.ConsumeVportEvents(vportEventsConsumer{dpif, consumer{done}}); err != nil {
		return printErr("%s", err)
	}

	<-done
	return true
}
Example #7
0
func DeleteDatapath(dpname string) error {
	dpif, err := odp.NewDpif()
	if err != nil {
		return err
	}
	defer dpif.Close()

	dp, err := dpif.LookupDatapath(dpname)
	if err != nil {
		if odp.IsNoSuchDatapathError(err) {
			return nil
		}
		return err
	}

	return dp.Delete()
}
Example #8
0
File: odp.go Project: CNDonny/scope
func CreateDatapath(dpname string) (err error, supported bool) {
	dpif, err := odp.NewDpif()
	if err != nil {
		if odp.IsKernelLacksODPError(err) {
			return nil, false
		}

		return err, true
	}

	defer dpif.Close()

	dp, err := dpif.CreateDatapath(dpname)
	if err != nil && !odp.IsDatapathNameAlreadyExistsError(err) {
		return err, true
	}

	// Pick an ephemeral port number to use in probing for vxlan
	// support.
	udpconn, err := net.ListenUDP("udp4", nil)
	if err != nil {
		return err, true
	}

	// we leave the UDP socket open, so creating a vxlan vport on
	// the same port number should fail.  But that's fine: It's
	// still sufficient to probe for support.
	portno := uint16(udpconn.LocalAddr().(*net.UDPAddr).Port)
	vpid, err := dp.CreateVport(odp.NewVxlanVportSpec(
		fmt.Sprintf("vxlan-%d", portno), portno))
	if nlerr, ok := err.(odp.NetlinkError); ok {
		if syscall.Errno(nlerr) == syscall.EAFNOSUPPORT {
			dp.Delete()
			return fmt.Errorf("kernel does not have Open vSwitch VXLAN support"), false
		}
	}

	if err == nil {
		dp.DeleteVport(vpid)
	}

	udpconn.Close()
	return nil, true
}
Example #9
0
File: main.go Project: awh/go-odp
func listFlows(f Flags) bool {
	var showStats bool
	f.BoolVar(&showStats, "stats", false, "show statistics")
	args := f.Parse(1, 1)

	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	dp, dpname := lookupDatapath(dpif, args[0])
	if dp == nil {
		return false
	}

	flows, err := dp.EnumerateFlows()
	if err != nil {
		return printErr("%s", err)
	}

	for _, flow := range flows {
		os.Stdout.WriteString(dpname)

		err = printFlowKeys(flow.FlowKeys, *dp)
		if err != nil {
			return printErr("%s", err)
		}

		err = printFlowActions(flow.Actions, *dp)
		if err != nil {
			return printErr("%s", err)
		}

		if showStats {
			fmt.Printf(": %d packets, %d bytes, used %d",
				flow.Packets, flow.Bytes, flow.Used)
		}

		os.Stdout.WriteString("\n")
	}

	return true
}
Example #10
0
File: main.go Project: awh/go-odp
func addFlow(f Flags) bool {
	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	dp, flow, ok := flagsToFlowSpec(f, dpif)
	if !ok {
		return false
	}

	err = dp.CreateFlow(flow)
	if err != nil {
		return printErr("%s", err)
	}

	return true
}
Example #11
0
File: main.go Project: awh/go-odp
func addVport(dpname string, spec odp.VportSpec) bool {
	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	dp, dpname := lookupDatapath(dpif, dpname)
	if dp == nil {
		return false
	}

	_, err = dp.CreateVport(spec)
	if err != nil {
		return printErr("%s", err)
	}

	return true
}
Example #12
0
File: main.go Project: awh/go-odp
func listenOnDatapath(f Flags) bool {
	var showKeys bool
	f.BoolVar(&showKeys, "keys", false, "show flow keys on reported packets")

	args := f.Parse(1, 1)

	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	dp, dpname := lookupDatapath(dpif, args[0])
	if dp == nil {
		return false
	}

	pipe, err := openTcpdump()
	if err != nil {
		return printErr("Error starting tcpdump: %s", err)
	}

	miss := func(packet []byte, flowKeys odp.FlowKeys) error {
		if showKeys {
			os.Stdout.WriteString("[" + dpname)
			if err := printFlowKeys(flowKeys, *dp); err != nil {
				return err
			}
			os.Stdout.WriteString("]\n")
		}

		return writeTcpdumpPacket(pipe, time.Now(), packet)
	}

	done := make(chan struct{})
	_, err = dp.ConsumeMisses(missConsumer{consumer{done}, miss})
	if err != nil {
		return printErr("%s", err)
	}

	<-done
	return true
}
Example #13
0
File: main.go Project: awh/go-odp
func addDatapath(f Flags) bool {
	args := f.Parse(1, 1)

	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	_, err = dpif.CreateDatapath(args[0])
	if err != nil {
		if odp.IsDatapathNameAlreadyExistsError(err) {
			return printErr("Network device named %s already exists", args[0])
		} else {
			return printErr("%s", err)
		}
	}

	return true
}
Example #14
0
File: main.go Project: awh/go-odp
func deleteDatapath(f Flags) bool {
	args := f.Parse(1, 1)

	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	dp, _ := lookupDatapath(dpif, args[0])
	if dp == nil {
		return false
	}

	err = dp.Delete()
	if err != nil {
		return printErr("%s", err)
	}

	return true
}
Example #15
0
File: main.go Project: awh/go-odp
func deleteFlow(f Flags) bool {
	dpif, err := odp.NewDpif()
	if err != nil {
		return printErr("%s", err)
	}
	defer dpif.Close()

	dp, flow, ok := flagsToFlowSpec(f, dpif)
	if !ok {
		return false
	}

	err = dp.DeleteFlow(flow.FlowKeys)
	if err != nil {
		if odp.IsNoSuchFlowError(err) {
			return printErr("No such flow")
		} else {
			return printErr("%s", err)
		}
	}

	return true
}
Example #16
0
func NewFastDatapath(dpName string, port int) (*FastDatapath, error) {
	dpif, err := odp.NewDpif()
	if err != nil {
		return nil, err
	}

	success := false
	defer func() {
		if !success {
			dpif.Close()
		}
	}()

	dp, err := dpif.LookupDatapath(dpName)
	if err != nil {
		return nil, err
	}

	iface, err := net.InterfaceByName(dpName)
	if err != nil {
		return nil, err
	}

	fastdp := &FastDatapath{
		dpname:        dpName,
		mtu:           iface.MTU,
		dpif:          dpif,
		dp:            dp,
		missHandlers:  make(map[odp.VportID]missHandler),
		sendToPort:    nil,
		sendToMAC:     make(map[MAC]bridgeSender),
		seenMACs:      make(map[MAC]struct{}),
		vxlanVportIDs: make(map[int]odp.VportID),
		forwarders:    make(map[mesh.PeerName]*fastDatapathForwarder),
	}

	// This delete happens asynchronously in the kernel, meaning that
	// we can sometimes fail to recreate the vxlan vport with EADDRINUSE -
	// consequently we retry a small number of times in
	// getVxlanVportIDHarder() to compensate.
	if err := fastdp.deleteVxlanVports(); err != nil {
		return nil, err
	}

	if err := fastdp.deleteFlows(); err != nil {
		return nil, err
	}

	// We use the weave port number plus 1 for vxlan.  Hard-coding
	// this relationship may seem dubious, but there is no moral
	// difference between this and requiring that the sleeve UDP
	// port number is the same as the TCP port number.  The hard
	// part would be not adding weaver flags to allow the port
	// numbers to be independent, but working out how to specify
	// them on the connecting side.  So we can wait to find out if
	// anyone wants that.
	fastdp.mainVxlanVportID, err = fastdp.getVxlanVportIDHarder(port+1, 5, time.Millisecond*10)
	if err != nil {
		return nil, err
	}

	// need to lock before we might receive events
	fastdp.lock.Lock()
	defer fastdp.lock.Unlock()

	if _, err := dp.ConsumeMisses(fastdp); err != nil {
		return nil, err
	}

	if _, err := dp.ConsumeVportEvents(fastdp); err != nil {
		return nil, err
	}

	vports, err := dp.EnumerateVports()
	if err != nil {
		return nil, err
	}

	for _, vport := range vports {
		fastdp.makeBridgeVport(vport)
	}

	success = true
	go fastdp.run()
	return fastdp, nil
}
Example #17
0
func NewFastDatapath(config FastDatapathConfig) (*FastDatapath, error) {
	dpif, err := odp.NewDpif()
	if err != nil {
		return nil, err
	}

	success := false
	defer func() {
		if !success {
			dpif.Close()
		}
	}()

	dp, err := dpif.LookupDatapath(config.DatapathName)
	if err != nil {
		return nil, err
	}

	iface, err := net.InterfaceByName(config.DatapathName)
	if err != nil {
		return nil, err
	}

	fastdp := &FastDatapath{
		dpname:        config.DatapathName,
		mtu:           iface.MTU,
		dpif:          dpif,
		dp:            dp,
		missHandlers:  make(map[odp.VportID]missHandler),
		sendToPort:    nil,
		sendToMAC:     make(map[MAC]bridgeSender),
		seenMACs:      make(map[MAC]struct{}),
		vxlanVportIDs: make(map[int]odp.VportID),
		forwarders:    make(map[PeerName]*fastDatapathForwarder),
	}

	if err := fastdp.deleteVxlanVports(); err != nil {
		return nil, err
	}

	if err := fastdp.deleteFlows(); err != nil {
		return nil, err
	}

	// We use the weave port number plus 1 for vxlan.  Hard-coding
	// this relationship may seem dubious, but there is no moral
	// difference between this and requiring that the sleeve UDP
	// port number is the same as the TCP port number.  The hard
	// part would be not adding weaver flags to allow the port
	// numbers to be independent, but working out how to specify
	// them on the connecting side.  So we can wait to find out if
	// anyone wants that.
	fastdp.mainVxlanVportID, err = fastdp.getVxlanVportID(config.Port + 1)
	if err != nil {
		return nil, err
	}

	// need to lock before we might receive events
	fastdp.lock.Lock()
	defer fastdp.lock.Unlock()

	if _, err := dp.ConsumeMisses(fastdp); err != nil {
		return nil, err
	}

	if _, err := dp.ConsumeVportEvents(fastdp); err != nil {
		return nil, err
	}

	vports, err := dp.EnumerateVports()
	if err != nil {
		return nil, err
	}

	for _, vport := range vports {
		fastdp.makeBridgeVport(vport)
	}

	success = true
	go fastdp.run()
	return fastdp, nil
}