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