コード例 #1
0
ファイル: main.go プロジェクト: hkwi/gopenflow
func main() {
	flag.Parse()
	args := flag.Args()

	getConn := func(spec string) io.ReadWriter {
		p := strings.SplitN(spec, ":", 2)
		if len(p) == 1 {
			panic(fmt.Sprintf("connection scheme failure %s", args[0]))
		} else if c, err := net.Dial(p[0], p[1]); err != nil {
			panic(err)
		} else if n, err := c.Write([]byte(hello)); n != 8 || err != nil {
			panic("hello send error")
		} else if res, err := gopenflow.ReadMessage(c); err != nil {
			panic(err)
		} else if res[0] != 4 {
			panic("openflow version error")
		} else if ofp4.Header(res).Type() != ofp4.OFPT_HELLO {
			panic("hello recv error")
		} else {
			return c
		}
	}

	switch args[1] {
	case "dump-flows":
		con := getConn(args[0])

		flowStatsReq := make([]byte, 32)
		flowStatsReq[0] = ofp4.OFPTT_ALL
		binary.BigEndian.PutUint32(flowStatsReq[4:], ofp4.OFPP_ANY)
		binary.BigEndian.PutUint32(flowStatsReq[8:], ofp4.OFPG_ANY)

		mphdr := make([]byte, 16)
		mphdr[0] = 4
		mphdr[1] = ofp4.OFPT_MULTIPART_REQUEST
		binary.BigEndian.PutUint16(mphdr[8:], ofp4.OFPMP_FLOW)

		msg := append(mphdr, append(flowStatsReq, ofp4.MakeMatch(nil)...)...)
		binary.BigEndian.PutUint16(msg[2:], uint16(len(msg)))
		con.Write(msg)

		for {
			var seq ofp4.FlowStats
			if msg, err := gopenflow.ReadMessage(con); err != nil {
				panic(err)
			} else if ofp4.Header(msg).Type() != ofp4.OFPT_MULTIPART_REPLY {
				panic("multipart error")
			} else if mp := ofp4.MultipartReply(msg); mp.Type() != ofp4.OFPMP_FLOW {
				panic("flow_stats reply error")
			} else {
				seq = ofp4.FlowStats(mp.Body())
			}
			var lines []string
			for _, stat := range seq.Iter() {
				lines = append(lines, fmt.Sprintf("%v pkts=%d bytes=%d dur=%d", stat, stat.PacketCount(), stat.ByteCount(), stat.DurationSec()))
			}
			sort.Sort(sort.Reverse(sort.StringSlice(lines)))
			for _, line := range lines {
				fmt.Print(line, "\n")
			}
			if binary.BigEndian.Uint16(mphdr[10:])&ofp4.OFPMPF_REPLY_MORE == 0 {
				break
			}
		}
	case "add-flow":
		flow := ofp4.FlowMod(make([]byte, 56))
		if err := flow.Parse(args[2]); err != nil {
			panic(err)
		} else {
			con := getConn(args[0])
			con.Write([]byte(flow))
			con.Write([]byte(barrier))
			if res, err := gopenflow.ReadMessage(con); err != nil {
				panic(err)
			} else if ofp4.Header(res).Type() == ofp4.OFPT_ERROR {
				log.Print("error")
			}
		}
	case "del-flows":
		flow := ofp4.FlowMod(make([]byte, 56))
		flow[25] = ofp4.OFPFC_DELETE
		if err := flow.Parse(args[2]); err != nil {
			panic(err)
		} else {
			con := getConn(args[0])
			con.Write([]byte(flow))
			con.Write([]byte(barrier))
			for {
				if res, err := gopenflow.ReadMessage(con); err != nil {
					panic(err)
				} else if ofp4.Header(res).Type() == ofp4.OFPT_BARRIER_REPLY {
					break
				} else {
					log.Print(res)
				}
			}
		}
	default:
		panic(fmt.Sprintf("unknown subcommand %s", args[1]))
	}
}
コード例 #2
0
ファイル: control.go プロジェクト: hkwi/gopenflow
func (self *ofmFlowMod) Map() Reducable {
	msg := ofp4.FlowMod(self.req)
	bufferId := msg.BufferId()

	switch msg.Command() {
	case ofp4.OFPFC_ADD:
		if err := self.pipe.addFlowEntry(msg); err != nil {
			if e, ok := err.(ofp4.ErrorMsg); ok {
				self.putError(e)
			} else {
				log.Print(err)
			}
		}
	case ofp4.OFPFC_MODIFY, ofp4.OFPFC_MODIFY_STRICT:
		reqMatch := match{}
		if err := reqMatch.UnmarshalBinary(msg.Match().OxmFields()); err != nil {
			log.Print(err)
		} else if msg.TableId() > ofp4.OFPTT_MAX {
			self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_FLOW_MOD_FAILED, ofp4.OFPFMFC_BAD_TABLE_ID))
		} else {
			filter := flowFilter{
				cookie:     msg.Cookie(),
				cookieMask: msg.CookieMask(),
				tableId:    msg.TableId(),
				outPort:    ofp4.OFPP_ANY,
				outGroup:   ofp4.OFPG_ANY,
				match:      reqMatch,
			}
			if msg.Command() == ofp4.OFPFC_MODIFY_STRICT {
				filter.priority = msg.Priority()
				filter.opStrict = true
			}
			for _, stat := range self.pipe.filterFlows(filter) {
				flow := stat.flow
				if err := func() error {
					flow.lock.Lock()
					defer flow.lock.Unlock()

					if msg.Flags()&ofp4.OFPFF_RESET_COUNTS != 0 {
						flow.packetCount = 0
						flow.byteCount = 0
					}
					return flow.importInstructions(msg.Instructions())
				}(); err != nil {
					if e, ok := err.(ofp4.ErrorMsg); ok {
						self.putError(e)
					} else {
						log.Print(err)
					}
				}
			}
		}
	case ofp4.OFPFC_DELETE, ofp4.OFPFC_DELETE_STRICT:
		reqMatch := match{}
		if err := reqMatch.UnmarshalBinary(msg.Match().OxmFields()); err != nil {
			log.Print(err)
		} else {
			filter := flowFilter{
				opUnregister: true,
				cookie:       msg.Cookie(),
				cookieMask:   msg.CookieMask(),
				tableId:      msg.TableId(),
				outPort:      msg.OutPort(),
				outGroup:     msg.OutGroup(),
				match:        reqMatch,
			}
			if msg.Command() == ofp4.OFPFC_DELETE_STRICT {
				filter.priority = msg.Priority()
				filter.opStrict = true
			}
			for _, stat := range self.pipe.filterFlows(filter) {
				if hdr, err := stat.flow.fields.MarshalBinary(); err != nil {
					log.Print(err)
				} else if portNo, act := hookDot11Action(oxm.Oxm(hdr)); portNo != 0 && len(act) != 0 {
					if port := self.pipe.getPort(portNo); port != nil {
						if err := port.Vendor(gopenflow.MgmtFrameRemove(act)).(error); err != nil {
							log.Print(err)
						}
					}
				}
				if stat.flow.flags&ofp4.OFPFF_SEND_FLOW_REM != 0 {
					self.pipe.sendFlowRem(stat.tableId, stat.priority, stat.flow, ofp4.OFPRR_DELETE)
				}
			}
		}
		bufferId = ofp4.OFP_NO_BUFFER // nothing to do with buffer by specification.
	}
	if bufferId != ofp4.OFP_NO_BUFFER {
		original, ok := func() (outputToPort, bool) {
			self.pipe.lock.Lock()
			defer self.pipe.lock.Unlock()

			original, ok := self.pipe.buffer[bufferId]
			if ok {
				delete(self.pipe.buffer, bufferId)
			}
			return original, ok
		}()
		if ok {
			pipe := self.pipe
			pipe.datapath <- &flowTask{
				Frame:   original.Frame,
				pipe:    self.pipe,
				tableId: 0,
			}
		} else {
			self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_BAD_REQUEST, ofp4.OFPBRC_BUFFER_UNKNOWN))
		}
	}
	return self
}