Пример #1
0
/* OFPT_FLOW_REMOVED async message */
func (self *Pipeline) sendFlowRem(tableId uint8, priority uint16, flow *flowEntry, reason uint8) {
	if fields, err := flow.fields.MarshalBinary(); err != nil {
		log.Print(err)
	} else {
		dur := time.Now().Sub(flow.created)
		msg := ofp4.MakeFlowRemoved(
			flow.cookie,
			priority,
			reason,
			tableId,
			uint32(dur/time.Second),
			uint32(dur%time.Second), // time.Nanosecond == 1
			flow.idleTimeout,
			flow.hardTimeout,
			flow.packetCount,
			flow.byteCount,
			ofp4.MakeMatch(fields))

		for _, ch := range self.channels {
			if ch.flowRemovedMask[0]&(1<<reason) == 0 {
				ch.Notify(msg)
			}
		}
	}
}
Пример #2
0
func (self *ofmMpFlow) Map() Reducable {
	pipe := self.pipe

	var flows []flowStats
	for _, req := range self.reqs {
		mreq := ofp4.FlowStatsRequest(req)
		var reqMatch match
		if e := reqMatch.UnmarshalBinary(mreq.Match().OxmFields()); e != nil {
			log.Print(e)
		} else {
			filter := flowFilter{
				tableId:    mreq.TableId(),
				outPort:    mreq.OutPort(),
				outGroup:   mreq.OutGroup(),
				cookie:     mreq.Cookie(),
				cookieMask: mreq.CookieMask(),
				match:      reqMatch,
			}
			for _, f := range pipe.filterFlows(filter) {
				hit := false
				for _, seen := range flows {
					if f.flow == seen.flow {
						hit = true
						break
					}
				}
				if !hit {
					flows = append(flows, f)
				}
			}
		}
	}
	for _, f := range flows {
		duration := time.Now().Sub(f.flow.created)
		if buf, e := f.flow.fields.MarshalBinary(); e != nil {
			log.Print(e)
		} else {
			chunk := ofp4.MakeFlowStats(
				f.tableId,
				uint32(duration.Seconds()),
				uint32(duration.Nanoseconds()%int64(time.Second)),
				f.priority,
				f.flow.idleTimeout,
				f.flow.hardTimeout,
				f.flow.flags, // OFPFF_
				f.flow.cookie,
				f.flow.packetCount,
				f.flow.byteCount,
				ofp4.MakeMatch(buf),
				f.flow.exportInstructions())
			self.chunks = append(self.chunks, chunk)
		}
	}
	return self
}
Пример #3
0
func (self *Pipeline) packetIn(buffer_id uint32, pout outputToPort) error {
	if fr, err := pout.getFrozen(); err != nil {
		return err
	} else {
		totalLen := len(fr.Data)
		if int(pout.maxLen) < totalLen {
			fr.Data = fr.Data[:pout.maxLen]
		}
		msg := ofp4.MakePacketIn(buffer_id,
			uint16(totalLen),
			pout.reason,
			pout.tableId,
			pout.cookie,
			ofp4.MakeMatch(fr.Oob),
			fr.Data)

		for _, ch := range self.channels {
			if ch.packetInMask[0]&(1<<pout.reason) == 0 {
				ch.Notify(msg)
			}
		}
		return nil
	}
}
Пример #4
0
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]))
	}
}