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) } }
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 }
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 }
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 }
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 }
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 }
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() }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }