// Rcvf receives the message and the context. func Rcvf(msg beehive.Msg, ctx beehive.RcvContext) error { // msg is an envelope around the Hello message. // You can retrieve the Hello, using msg.Data() and then // you need to assert that its a Hello. hello := msg.Data().(Hello) // Using ctx.Dict you can get (or create) a dictionary. dict := ctx.Dict("hello_dict") // Using Get(), you can get the value associated with // a key in the dictionary. Keys are always string // and values are generic interface{}'s. v, err := dict.Get(hello.Name) // If there is an error, the entry is not in the // dictionary. Otherwise, we set cnt based on // the value we already have in the dictionary // for that name. cnt := 0 if err == nil { cnt = v.(int) } // Now we increment the count. cnt++ // And then we print the hello message. ctx.Printf("hello %s (%d)!\n", hello.Name, cnt) // Finally we update the count stored in the dictionary. return dict.Put(hello.Name, cnt) }
func (c *Calculator) Rcv(msg bh.Msg, ctx bh.RcvContext) error { op := msg.Data().(Op) res := c.calc(op) fmt.Printf("%d %s %d = %d\n", op.Lhs, op.OpT, op.Rhs, res) ctx.Reply(msg, res) return nil }
func confirmFlowEntryForPath(flow nom.FlowEntry, ctx bh.RcvContext) error { d := ctx.Dict(dictPath) v, err := d.Get(flow.ID) if err != nil { return fmt.Errorf("path: flow not found: %v", err) } pf := v.(pathAndFlows) for i := range pf.Flows { if pf.Flows[i].Flow.Equals(flow) { if pf.Flows[i].Installed { return fmt.Errorf("%v is already installed", flow) } pf.Flows[i].Installed = true pf.Installed++ break } } if pf.Installed == len(pf.Flows) { ctx.SendToCell(nom.PathAdded{Path: pf.Path}, pf.Subscriber.App, pf.Subscriber.Cell()) } return d.Put(flow.ID, pf) }
// The bee hander func BeeHandler( beehiveMessage beehive.Msg, beeContext beehive.RcvContext) error { // beehiveMessage is an envelope around the Hello message. // You can retrieve the Hello, using msg.Data() and then // you need to assert that its a MessageToBee. message := beehiveMessage.Data().(MessageToBee) // Using ctx.Dict you can get (or create) a dictionary. dict := beeContext.Dict("beehive-app-dict") value, err := dict.Get(message.DestinationBee) logger.Trace.Printf("[BeeHandler] Message sent to bee with id (%s) \n", message.DestinationBee) count := 0 if err == nil { // No error mean there is already an item with given key count = value.(int) } count++ logger.Trace.Printf("[BeeHandler] Count = %d\n", count) logger.Trace.Printf("[BeeHandler] Calculate fib number %d\n", message.FibNumber) Fib(message.FibNumber) beeContext.Reply(beehiveMessage, count) return dict.Put(message.DestinationBee, count) }
func (h EnQHandler) Rcv(msg beehive.Msg, ctx beehive.RcvContext) error { enq := msg.Data().(Enque) dict := ctx.Dict(active) next := TaskID(1) if v, err := dict.Get("_next_"); err == nil { next = v.(TaskID) } key := next.String() task := Task{ Queue: enq.Queue, ID: next, Body: enq.Body, } if err := dict.Put(key, task); err != nil { return err } if err := dict.Put("_next_", next+1); err != nil { return err } enqued := Enqued{ ID: enq.ID, Queue: enq.Queue, TaskID: next, } return ctx.Reply(msg, enqued) }
func (h portStatusHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { // FIXME(soheil): This implementation is very naive and cannot tolerate // faults. We need to first check if the driver is the mater, and then apply // the change. Otherwise, we need to enque this message for that driver and // make sure we apply the log to the port status data := msg.Data().(nom.PortStatusChanged) dict := ctx.Dict(driversDict) k := string(data.Port.Node) v, err := dict.Get(k) if err != nil { return fmt.Errorf("NOMController: node %v not found", data.Port.Node) } n := v.(nodeDrivers) if !n.isMaster(data.Driver) { glog.Warningf("NOMController: %v ignored, %v is not master, master is %v", data.Port, data.Driver, n.master()) return nil } if p, ok := n.Ports.GetPort(data.Port.UID()); ok { if p == data.Port { return fmt.Errorf("NOMController: duplicate port status change for %v", data.Port) } n.Ports.DelPort(p) } n.Ports.AddPort(data.Port) ctx.Emit(nom.PortUpdated(data.Port)) return nil }
// NodesCentralized returns the nodes with outgoing links so far. // // Note that this methods should be used only when the GraphBuilderCentralized // is in use. func NodesCentralized(ctx bh.RcvContext) (nodes []nom.UID) { ctx.Dict(GraphDict).ForEach(func(k string, v interface{}) bool { nodes = append(nodes, nom.UID(k)) return true }) return nodes }
func (h HealthChecker) Rcv(msg bh.Msg, ctx bh.RcvContext) error { db := msg.From() dict := ctx.Dict(driversDict) dict.ForEach(func(k string, v interface{}) { nd := v.(nodeDrivers) updated := false for i := range nd.Drivers { if nd.Drivers[i].BeeID == db { nd.Drivers[i].LastSeen = time.Now() // TODO(soheil): Maybe if outpings was more than MaxPings we // should emit a connected message. nd.Drivers[i].OutPings-- updated = true } } if !updated { return } if err := dict.Put(k, nd); err != nil { glog.Warningf("error in encoding drivers: %v", err) } }) return nil }
// Rcv method of the composed handler. func (c *ComposedHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { var err error for i := range c.Handlers { if c.Isolate { rctx := composedRcvContext{RcvContext: ctx, prefix: strconv.Itoa(i)} err = c.callRcv(c.Handlers[i], msg, rctx) } else { err = c.callRcv(c.Handlers[i], msg, ctx) } switch c.Composer(msg, ctx, err) { case Abort: ctx.AbortTx() return nil case Commit: ctx.CommitTx() return nil case Continue: if i == len(c.Handlers)-1 { if err == nil { ctx.CommitTx() } else { ctx.AbortTx() } return nil } case ContinueOrAbort: if i == len(c.Handlers)-1 { ctx.AbortTx() return nil } } } return nil }
func (b GraphBuilderCentralized) Rcv(msg bh.Msg, ctx bh.RcvContext) error { dict := ctx.Dict(GraphDict) var link nom.Link switch dm := msg.Data().(type) { case nom.LinkAdded: link = nom.Link(dm) case nom.LinkDeleted: link = nom.Link(dm) default: return fmt.Errorf("GraphBuilderCentralized: unsupported message type %v", msg.Type()) } nf, _ := nom.ParsePortUID(link.From) nt, _ := nom.ParsePortUID(link.To) if nf == nt { return fmt.Errorf("%v is a loop", link) } k := string(nf) links := make(map[nom.UID][]nom.Link) if v, err := dict.Get(k); err == nil { links = v.(map[nom.UID][]nom.Link) } links[nt.UID()] = append(links[nt.UID()], link) return dict.Put(k, links) }
func (h *httpHostListHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { hrq := msg.Data().(http.HTTPRequest) if hrq.AppName == "host" && hrq.Verb == "list" { dict := ctx.Dict(hostDict) v, err := dict.Get("hsts") hsts := []nom.Host{} if err == nil { hsts = v.([]nom.Host) } data, err := json.Marshal(hsts) if err != nil { glog.Errorf("Host list JSON marshaling: %v", err) return err } fmt.Println(hsts) hrs := http.HTTPResponse{ AppName: "host", Data: data, } err = ctx.Reply(msg, hrs) if err != nil { glog.Errorf("Replay error: %v", err) return err } } return nil }
func (h *arpPktInHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { pin := msg.Data().(nom.PacketIn) p := gopacket.NewPacket([]byte(pin.Packet), layers.LayerTypeEthernet, gopacket.Default) etherlayer := p.Layer(layers.LayerTypeEthernet) if etherlayer == nil { return nil } e, _ := etherlayer.(*layers.Ethernet) if e.EthernetType != layers.EthernetTypeARP { return nil } host, _, err := decodeARP([]byte(pin.Packet)) host.Node = pin.Node if err != nil { glog.Errorf("ARP decoding error: %v", err) return err } glog.V(2).Infof("Host detected: %v", host) ctx.Emit(nom.HostConnected(host)) return nil }
func (h *hostConnectedHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { host := msg.Data().(nom.HostConnected) dict := ctx.Dict(hostDict) _, err := dict.Get(host.MACAddr.String()) if err == nil { return nil } v, err := dict.Get("hsts") hsts := []nom.Host{} if err == nil { hsts = v.([]nom.Host) } hsts = append(hsts, nom.Host(host)) err = dict.Put(host.MACAddr.String(), host) if err != nil { glog.Errorf("Put %v in %s: %v", host, host.MACAddr.String(), err) return err } err = dict.Put("hsts", hsts) if err != nil { glog.Errorf("Put %v in hsts: %v", hsts, err) return err } ctx.Emit(nom.HostJoined(host)) return nil }
func (d *Driver) Rcv(m beehive.Msg, ctx beehive.RcvContext) error { if m.NoReply() { return nil } q, ok := m.Data().(StatQuery) if !ok { return nil } s, ok := d.switches[q.Switch] if !ok { return fmt.Errorf("No switch stored in the driver: %+v", s) } for i, f := range s.Flows { f.Bytes += uint64(rand.Intn(maxSpike)) s.Flows[i] = f glog.V(2).Infof("Emitting stat result for %+v", f) ctx.Emit(StatResult{q, f.Flow, f.Bytes}) } d.switches[q.Switch] = s return nil }
func (h *ConnHandler) handleAck(req ReqID, ctx beehive.RcvContext, r *bufio.Reader) error { q, err := r.ReadString(' ') if err != nil { return err } q = q[:len(q)-1] s, err := r.ReadString('\n') if err != nil { return err } s = dropNewLine(s) tid, err := strconv.ParseUint(s, 10, 64) if err != nil { return err } ctx.Emit(Ack{ ID: req, Queue: Queue(q), TaskID: TaskID(tid), }) return nil }
func (h *intentHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { hrq := msg.Data().(http.HTTPRequest) if hrq.AppName == "intent" && hrq.Verb == "build" { spd := shortestPathData{} err := json.Unmarshal(hrq.Data, &spd) if err != nil { glog.Errorf("Host list JSON unmarshaling: %v", err) return err } fmt.Println(spd) fmt.Println(discovery.ShortestPathCentralized(spd.From, spd.To, ctx)) hrs := http.HTTPResponse{ AppName: "host", Data: []byte{'A'}, } err = ctx.Reply(msg, hrs) if err != nil { glog.Errorf("Replay error: %v", err) return err } } return nil }
func (l *ofListener) startOFConn(conn net.Conn, ctx bh.RcvContext) { ofc := &ofConn{ HeaderConn: of.NewHeaderConn(conn), readBufLen: l.readBufLen, } ctx.StartDetached(ofc) }
func (r Router) neighbors(node Node, ctx bh.RcvContext) Edges { dict := ctx.Dict(neighDict) var neighs Edges if v, err := dict.Get(node.Key()); err == nil { neighs = v.(Edges) } return neighs }
func (p Poller) Rcv(msg bh.Msg, ctx bh.RcvContext) error { ctx.Dict("Switches").ForEach(func(k string, v interface{}) { fmt.Printf("poller: polling switch %v\n", k) ctx.Emit(nom.FlowStatsQuery{ Node: nom.UID(k), }) }) return nil }
func (r Router) appendNieghbor(edge Edge, ctx bh.RcvContext) error { neighs := r.neighbors(edge.To, ctx) if neighs.Contains(edge) { return fmt.Errorf("%v is already a neighbor", edge) } neighs = append(neighs, edge) ctx.Dict(neighDict).Put(edge.To.Key(), neighs) return nil }
func (h *nodeLeftHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { n := nom.Node(msg.Data().(nom.NodeLeft)) d := ctx.Dict(nodeDict) k := string(n.UID()) if _, err := d.Get(k); err != nil { return fmt.Errorf("%v is not joined", n) } d.Del(k) return nil }
func reservePathID(ctx bh.RcvContext) uint64 { d := ctx.Dict(dictID) var id uint64 if v, err := d.Get("path"); err == nil { id = v.(uint64) } id++ d.Put("path", id) return id - 1 }
func reserveFlowID(ctx bh.RcvContext, cnt int) uint64 { d := ctx.Dict(dictID) var id uint64 if v, err := d.Get("flow"); err == nil { id = v.(uint64) } id += uint64(cnt) d.Put("flow", id) return id - uint64(cnt) }
func (h *timeoutHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { d := ctx.Dict(nodeDict) d.ForEach(func(k string, v interface{}) { np := v.(nodePortsAndLinks) for _, p := range np.P { sendLLDPPacket(np.N, p, ctx) } }) return nil }
func (h addTriggerHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { add := msg.Data().(nom.AddTrigger) dict := ctx.Dict(triggersDict) var nt nodeTriggers if v, err := dict.Get(string(add.Node)); err == nil { nt = v.(nodeTriggers) } nt.maybeAddTrigger(nom.Trigger(add)) return dict.Put(string(add.Node), nt) }
func (h *UpdateHandler) Rcv(m beehive.Msg, ctx beehive.RcvContext) error { if m.NoReply() { return nil } u := m.Data().(MatrixUpdate) glog.Infof("Received matrix update: %+v", u) ctx.Emit(FlowMod{Switch: u.Switch}) return nil }
func (r Router) routingTable(from Node, ctx bh.RcvContext) RoutingTable { dict := ctx.Dict(routeDict) var tbl RoutingTable if v, err := dict.Get(from.Key()); err == nil { tbl = v.(RoutingTable) } else { tbl = make(RoutingTable) } return tbl }
func (h delTriggerHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { del := msg.Data().(nom.DelTrigger) var nt nodeTriggers dict := ctx.Dict(triggersDict) if v, err := dict.Get(string(del.Node)); err == nil { nt = v.(nodeTriggers) } nt.delTrigger(nom.Trigger(del)) return dict.Put(string(del.Node), nt) }
func (h Hub) Rcv(msg bh.Msg, ctx bh.RcvContext) error { in := msg.Data().(nom.PacketIn) out := nom.PacketOut{ Node: in.Node, InPort: in.InPort, BufferID: in.BufferID, Packet: in.Packet, Actions: []nom.Action{nom.ActionFlood{}}, } ctx.ReplyTo(msg, out) return nil }
// ShortestPathCentralized calculates the shortest path from node "from" to node // "to" according to the state stored in GraphDict by the // GraphBuilderCentralized. // // This method is not go-routine safe and must be called within a handler of the // application that uses the GraphBuilderCentralized as a handler. Otherwise, // the user needs to synchronize the two. func ShortestPathCentralized(from, to nom.UID, ctx bh.RcvContext) ( paths [][]nom.Link, length int) { if from == to { return nil, 0 } visited := make(map[nom.UID]distAndLinks) visited[from] = distAndLinks{Dist: 0} pq := nodeAndDistSlice{{Dist: 0, Node: from}} heap.Init(&pq) dict := ctx.Dict(GraphDict) for len(pq) != 0 { nd := heap.Pop(&pq).(nodeAndDist) if nd.Node == to { continue } nodeLinks := make(map[nom.UID][]nom.Link) if v, err := dict.Get(string(nd.Node)); err == nil { nodeLinks = v.(map[nom.UID][]nom.Link) } nd.Dist = visited[nd.Node].Dist for _, links := range nodeLinks { for _, l := range links { nid, _ := nom.ParsePortUID(l.To) ton := nom.UID(nid) if dl, ok := visited[ton]; ok { switch { case nd.Dist+1 < dl.Dist: glog.Fatalf("invalid distance in BFS") case nd.Dist+1 == dl.Dist: dl.BackLinks = append(dl.BackLinks, l) visited[ton] = dl } continue } visited[ton] = distAndLinks{ Dist: nd.Dist + 1, BackLinks: []nom.Link{l}, } ndto := nodeAndDist{ Dist: nd.Dist + 1, Node: ton, } heap.Push(&pq, ndto) } } } return allPaths(from, to, visited) }