/* 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) } } } }
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 }
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 } }
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])) } }