コード例 #1
0
ファイル: control.go プロジェクト: hkwi/gopenflow
func (self *ofmMpMeterConfig) Map() Reducable {
	mpreq := ofp4.MeterMultipartRequest(ofp4.MultipartRequest(self.req).Body())
	meterId := mpreq.MeterId()
	for meterId, meter := range self.pipe.getMeters(meterId) {
		var bands []byte
		for _, b := range meter.bands {
			if bin, err := b.MarshalBinary(); err != nil {
				panic(err)
			} else {
				bands = append(bands, bin...)
			}
		}
		var flags uint16
		if meter.flagPkts {
			flags |= ofp4.OFPMF_PKTPS
		} else {
			flags |= ofp4.OFPMF_KBPS
		}
		if meter.flagBurst {
			flags |= ofp4.OFPMF_BURST
		}
		if meter.flagStats {
			flags |= ofp4.OFPMF_STATS
		}
		chunk := ofp4.MakeMeterConfig(flags, meterId, bands)
		self.chunks = append(self.chunks, chunk)
	}
	return self
}
コード例 #2
0
ファイル: control.go プロジェクト: hkwi/gopenflow
func (self *ofmMpMeter) Map() Reducable {
	pipe := self.pipe

	meterId := ofp4.MeterMultipartRequest(ofp4.MultipartRequest(self.req).Body()).MeterId()
	for meterId, meter := range pipe.getMeters(meterId) {
		duration := time.Now().Sub(meter.created)
		var bands []byte
		for _, b := range meter.bands {
			bands = append(bands, ofp4.MakeMeterBandStats(b.getPacketCount(), b.getByteCount())...)
		}
		flowCount := len(pipe.filterFlows(flowFilter{
			tableId:  ofp4.OFPTT_ALL,
			outPort:  ofp4.OFPP_ANY,
			outGroup: ofp4.OFPG_ANY,
			meterId:  meterId,
		}))
		chunk := ofp4.MakeMeterStats(
			meterId,
			uint32(flowCount),
			meter.packetCount,
			meter.byteCount,
			uint32(duration.Seconds()),
			uint32(duration.Nanoseconds()%int64(time.Second)),
			bands)
		self.chunks = append(self.chunks, chunk)
	}
	return self
}
コード例 #3
0
ファイル: control.go プロジェクト: hkwi/gopenflow
func (self *ofmMpAggregate) Map() Reducable {
	mpreq := ofp4.MultipartRequest(self.req)
	mreq := ofp4.AggregateStatsRequest(mpreq.Body())

	var reqMatch match
	if err := reqMatch.UnmarshalBinary(mreq.Match().OxmFields()); err != nil {
		log.Print(err)
	} else {
		filter := flowFilter{
			tableId:    mreq.TableId(),
			outPort:    mreq.OutPort(),
			outGroup:   mreq.OutGroup(),
			cookie:     mreq.Cookie(),
			cookieMask: mreq.CookieMask(),
			match:      reqMatch,
		}
		var packetCount uint64
		var byteCount uint64
		var flowCount uint32
		for _, f := range self.pipe.filterFlows(filter) {
			packetCount += f.flow.packetCount
			byteCount += f.flow.byteCount
			flowCount++
		}
		var chunk ofp4.AggregateStatsReply

		self.chunks = append(self.chunks, chunk)
	}
	return self
}
コード例 #4
0
ファイル: control.go プロジェクト: hkwi/gopenflow
func (self *ofmMulti) Reduce() {
	msg := ofp4.MultipartRequest(self.req)
	payloadMaxLength := math.MaxUint16 - 16

	var payload []byte
	var payloadLength int
	for _, chunk := range self.chunks {
		payloadLength += len(chunk)
		if payloadLength >= payloadMaxLength {
			msg := ofp4.MakeMultipartReply(
				msg.Type(),
				ofp4.OFPMPF_REPLY_MORE,
				payload)
			self.resps = append(self.resps, msg.SetXid(self.req.Xid()))
			payload = payload[:0]
			payloadLength = 0
		}
		payload = append(payload, chunk...)
	}
	{
		msg := ofp4.MakeMultipartReply(
			msg.Type(),
			0,
			payload)
		self.resps = append(self.resps, msg.SetXid(self.req.Xid()))
	}
	self.ofmReply.Reduce()
}
コード例 #5
0
ファイル: control.go プロジェクト: hkwi/gopenflow
func (self *ofmMpPortStats) Map() Reducable {
	mpreq := ofp4.MultipartRequest(self.req)

	proc := func(portNo uint32, port gopenflow.Port) {
		var pstats gopenflow.PortStats
		var ethinfo gopenflow.PortStatsEthernet
		if p, err := port.Stats(); err != nil {
			log.Print(err)
		} else {
			pstats = p
			if p.Ethernet != nil {
				ethinfo = *p.Ethernet
			}
		}
		duration := self.pipe.portAlive[portNo].Total()
		chunk := ofp4.MakePortStats(
			portNo,
			pstats.RxPackets,
			pstats.TxPackets,
			pstats.RxBytes,
			pstats.TxBytes,
			pstats.RxDropped,
			pstats.TxDropped,
			pstats.RxErrors,
			pstats.TxErrors,
			ethinfo.RxFrameErr,
			ethinfo.RxOverErr,
			ethinfo.RxCrcErr,
			ethinfo.Collisions,
			uint32(duration.Seconds()),
			uint32(duration.Nanoseconds()%int64(time.Second)),
		)
		self.chunks = append(self.chunks, chunk)
	}

	portNo := ofp4.PortStatsRequest(mpreq.Body()).PortNo()
	switch portNo {
	default:
		if portNo > 0 && portNo <= ofp4.OFPP_MAX {
			if port := self.pipe.getPort(portNo); port != nil {
				proc(portNo, port)
			} else {
				self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_PORT_MOD_FAILED, ofp4.OFPPMFC_BAD_PORT))
			}
		} else {
			self.putError(ofp4.MakeErrorMsg(ofp4.OFPET_PORT_MOD_FAILED, ofp4.OFPPMFC_BAD_PORT))
		}
	case ofp4.OFPP_ALL, ofp4.OFPP_ANY:
		for portNo, port := range self.pipe.getAllPorts() {
			proc(portNo, port)
		}
	}
	return self
}
コード例 #6
0
ファイル: pipeline.go プロジェクト: hkwi/gopenflow
func (self *Pipeline) AddChannel(conn io.ReadWriteCloser) error {
	self.lock.Lock()
	defer self.lock.Unlock()

	ch := &channel{
		Conn: conn,
	}

	// process hello
	ch.Notify(ofp4.MakeHello(ofp4.MakeHelloElemVersionbitmap([]uint32{uint32(1 << 4)})))
	head := make([]byte, 4)
	if msg, err := readOfpMessage(conn, head); err != nil {
		return err
	} else if ofp4.Header(msg).Type() != ofp4.OFPT_HELLO {
		return fmt.Errorf("The first message must be HELLO")
	} else {
		satisfied := false
		for _, element := range ofp4.Hello(msg).Elements().Iter() {
			switch element.Type() {
			case ofp4.OFPHET_VERSIONBITMAP:
				bitmaps := ofp4.HelloElemVersionbitmap(element).Bitmaps()
				if len(bitmaps) > 0 && (bitmaps[0]&(1<<4) != 0) {
					satisfied = true
				}
				// ensure there be no bits higher than ofp4
				for i, b := range bitmaps {
					if i == 0 && (b&0xFFFFFFE0) != 0 {
						satisfied = false
					}
					if i > 0 && b != 0 {
						satisfied = false
					}
				}
			}
		}
		if !satisfied && ofp4.Header(msg).Version() == 4 {
			satisfied = true
		}
		if !satisfied {
			err := ofp4.MakeErrorMsg(
				ofp4.OFPET_HELLO_FAILED,
				ofp4.OFPHFC_INCOMPATIBLE,
			)
			ch.Response(ofp4.Header(err).SetXid(ofp4.Header(msg).Xid()))
			return err
		}
	}

	self.channels = append(self.channels, ch)

	worker := make(chan MapReducable)
	go MapReduce(worker, 4)
	go func() {
		defer close(worker)
		defer conn.Close()

		multipartCollect := make(map[uint32][][]byte)
		for {
			msg, err := readOfpMessage(conn, head)
			if err != nil {
				log.Print(err)
				break
			}
			reply := ofmReply{pipe: self, channel: ch, req: msg}
			switch ofp4.Header(msg).Type() {
			case ofp4.OFPT_ERROR:
				log.Print("got unexpected OFPT_ERROR")
			case ofp4.OFPT_ECHO_REQUEST:
				worker <- &ofmEcho{reply}
			case ofp4.OFPT_ECHO_REPLY:
				log.Print("got unexpected OFPT_ECHO_REPLY")
			case ofp4.OFPT_EXPERIMENTER:
				worker <- &ofmExperimenter{reply}
			case ofp4.OFPT_FEATURES_REQUEST:
				worker <- &ofmFeaturesRequest{reply}
			case ofp4.OFPT_GET_CONFIG_REQUEST:
				worker <- &ofmGetConfigRequest{reply}
			case ofp4.OFPT_SET_CONFIG:
				worker <- &ofmSetConfig{reply}
			case ofp4.OFPT_PACKET_OUT:
				worker <- &ofmPacketOut{ofmOutput{reply, nil}}
			case ofp4.OFPT_FLOW_MOD:
				worker <- &ofmFlowMod{ofmOutput{reply, nil}}
			case ofp4.OFPT_GROUP_MOD:
				worker <- &ofmGroupMod{reply}
			case ofp4.OFPT_PORT_MOD:
				worker <- &ofmPortMod{reply}
			case ofp4.OFPT_TABLE_MOD:
				worker <- &ofmTableMod{reply}
			case ofp4.OFPT_MULTIPART_REQUEST:
				xid := ofp4.Header(msg).Xid()
				req := ofp4.MultipartRequest(msg)

				multipartCollect[xid] = append(multipartCollect[xid], req.Body())
				if req.Flags()&ofp4.OFPMPF_REQ_MORE == 0 {
					reqs := multipartCollect[xid]
					delete(multipartCollect, xid)

					mreply := ofmMulti{
						ofmReply: reply,
						reqs:     reqs,
						chunks:   nil,
					}

					// capture
					switch req.Type() {
					case ofp4.OFPMP_DESC:
						worker <- &ofmMpDesc{mreply}
					case ofp4.OFPMP_TABLE:
						worker <- &ofmMpTable{mreply}
					case ofp4.OFPMP_GROUP_DESC:
						worker <- &ofmMpGroupDesc{mreply}
					case ofp4.OFPMP_GROUP_FEATURES:
						worker <- &ofmMpGroupFeatures{mreply}
					case ofp4.OFPMP_METER_FEATURES:
						worker <- &ofmMpMeterFeatures{mreply}
					case ofp4.OFPMP_PORT_DESC:
						worker <- &ofmMpPortDesc{mreply}
					case ofp4.OFPMP_FLOW:
						worker <- &ofmMpFlow{mreply}
					case ofp4.OFPMP_AGGREGATE:
						worker <- &ofmMpAggregate{mreply}
					case ofp4.OFPMP_PORT_STATS:
						worker <- &ofmMpPortStats{mreply}
					case ofp4.OFPMP_QUEUE:
						worker <- &ofmMpQueue{mreply}
					case ofp4.OFPMP_GROUP:
						worker <- &ofmMpGroup{mreply}
					case ofp4.OFPMP_METER:
						worker <- &ofmMpMeter{mreply}
					case ofp4.OFPMP_METER_CONFIG:
						worker <- &ofmMpMeterConfig{mreply}
					case ofp4.OFPMP_TABLE_FEATURES:
						worker <- &ofmMpTableFeatures{mreply}
					case ofp4.OFPMP_EXPERIMENTER:
						worker <- &ofmMpExperimenter{mreply}
					default:
						panic("unknown ofp_multipart_request.type")
					}
				}
			case ofp4.OFPT_BARRIER_REQUEST:
				for xid, _ := range multipartCollect {
					buf := ofp4.Header(make([]byte, 8))
					buf.SetXid(xid)
					rep := ofmReply{pipe: self, channel: ch, req: buf}
					rep.createError(ofp4.OFPET_BAD_REQUEST, ofp4.OFPBRC_BAD_MULTIPART)
					worker <- &rep
					delete(multipartCollect, xid)
				}
				worker <- &ofmBarrierRequest{reply}
			case ofp4.OFPT_QUEUE_GET_CONFIG_REQUEST:
				worker <- &ofmQueueGetConfigRequest{reply}
			case ofp4.OFPT_ROLE_REQUEST:
				worker <- &ofmRoleRequest{reply}
			case ofp4.OFPT_GET_ASYNC_REQUEST:
				worker <- &ofmGetAsyncRequest{reply}
			case ofp4.OFPT_SET_ASYNC:
				worker <- &ofmSetAsync{reply}
			case ofp4.OFPT_METER_MOD:
				worker <- &ofmMeterMod{reply}
			default:
				fmt.Printf("unknown ofp_header.type %v\n", msg)
				return
			}
		}
	}()
	return nil
}