func (h *newLinkHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { l := nom.Link(msg.Data().(NewLink)) n, _ := nom.ParsePortUID(l.From) d := ctx.Dict(nodeDict) k := string(n) v, err := d.Get(k) if err != nil { return nil } np := v.(nodePortsAndLinks) if oldl, ok := np.linkFrom(l.From); ok { if oldl.UID() == l.UID() { return nil } np.removeLink(oldl) ctx.Emit(nom.LinkDeleted(oldl)) } glog.V(2).Infof("Link detected %v", l) ctx.Emit(nom.LinkAdded(l)) np.L = append(np.L, l) return d.Put(k, np) }
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 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 }
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 *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 (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 (c *Collector) Rcv(m beehive.Msg, ctx beehive.RcvContext) error { res := m.Data().(StatResult) glog.V(2).Infof("Stat results: %+v", res) matrix := ctx.Dict(matrixDict) key := res.Switch.Key() v, err := matrix.Get(key) if err != nil { return fmt.Errorf("No such switch in matrix: %+v", res) } c.poller.query <- StatQuery{res.Switch} sw := v.(SwitchStats) stat, ok := sw[res.Flow] sw[res.Flow] = res.Bytes glog.V(2).Infof("Previous stats: %+v, Now: %+v", stat, res.Bytes) if !ok || res.Bytes-stat > c.delta { glog.Infof("Found an elephent flow: %+v, %+v, %+v", res, stat, ctx.Hive().ID()) ctx.Emit(MatrixUpdate(res)) } matrix.Put(key, sw) return nil }
func addFlowEntriesForPath(sub bh.AppCellKey, path nom.Path, flows []nom.FlowEntry, ctx bh.RcvContext) { fs := make([]flowAndStatus, 0, len(flows)) path.ID = strconv.FormatUint(reservePathID(ctx), 16) for i := range flows { flows[i].ID = path.ID fs = append(fs, flowAndStatus{Flow: flows[i]}) } pf := pathAndFlows{ Subscriber: sub, Path: path, Flows: fs, Timestamp: time.Now(), } d := ctx.Dict(dictPath) if err := d.Put(path.ID, pf); err != nil { glog.Fatalf("error in storing path entry: %v", err) } ack := centralizedAppCellKey(ctx.App()) for _, f := range flows { addf := nom.AddFlowEntry{ Flow: f, Subscriber: ack, } ctx.Emit(addf) } }
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 (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 (p *pinger) Rcv(msg bh.Msg, ctx bh.RcvContext) error { dict := ctx.Dict(PingPongDict) data := msg.Data() switch data := data.(type) { case ping: fmt.Printf("Rx Ping %d %v->%v\n", data.Seq, msg.From(), ctx.ID()) time.Sleep(300 * time.Millisecond) v, err := dict.Get("ping") var p ping if err == nil { p = v.(ping) } if data != p { return fmt.Errorf("Invalid ping: ping=%d, want=%d", data.Seq, p.Seq) } p.Seq += 1 dict.Put("ping", p) fmt.Printf("Ping stored to %v\n", p.Seq) if !msg.NoReply() { fmt.Printf("Tx Pong %d @ %v\n", data.pong().Seq, ctx.ID()) ctx.Emit(data.pong()) } case pong: fmt.Printf("Rx Pong %d %v->%v\n", data.Seq, msg.From(), ctx.ID()) time.Sleep(300 * time.Millisecond) dict := ctx.Dict(PingPongDict) v, err := dict.Get("pong") var p pong if err == nil { p = v.(pong) } if data != p { return fmt.Errorf("Invalid pong: pong=%d, want=%d", data.Seq, p.Seq) } p.Seq += 1 dict.Put("pong", p) fmt.Printf("Pong stored to %v\n", p.Seq) fmt.Printf("Tx Ping %d @ %v\n", data.ping().Seq, ctx.ID()) ctx.Emit(data.ping()) } return nil }
// Start is called once the detached handler starts. func (h *HelloConn) Start(ctx beehive.RcvContext) { defer h.conn.Close() r := bufio.NewReader(h.conn) for { name, _, err := r.ReadLine() if err != nil { return } ctx.Emit(HelloDetached{Name: string(name)}) } }
func sendLLDPPacket(n nom.Node, p nom.Port, ctx bh.RcvContext) { pkt := nom.PacketOut{ Node: n.UID(), Packet: nom.Packet(encodeLLDP(n, p)), BufferID: 0xFFFFFFFF, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{p.UID()}, }, }, } ctx.Emit(pkt) }
func (h *ConnHandler) handleDeQ(req ReqID, ctx beehive.RcvContext, r *bufio.Reader) error { q, err := r.ReadString('\n') if err != nil { return err } q = dropNewLine(q) ctx.Emit(Deque{ ID: req, Queue: Queue(q), }) return nil }
func (h addFlowHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { add := msg.Data().(nom.AddFlowEntry) var nf nodeFlows if v, err := ctx.Dict(flowsDict).Get(string(add.Flow.Node)); err == nil { nf = v.(nodeFlows) } added := nom.FlowEntryAdded{Flow: add.Flow} if nf.maybeAddFlow(add) { ctx.Emit(added) sendToMaster(add, add.Flow.Node, ctx) } if !add.Subscriber.IsNil() { ctx.SendToCell(added, add.Subscriber.App, add.Subscriber.Cell()) } return ctx.Dict(flowsDict).Put(string(add.Flow.Node), nf) }
func (h nodeConnectedHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { nc := msg.Data().(nom.NodeConnected) ddict := ctx.Dict(driversDict) k := string(nc.Node.ID) n := nodeDrivers{ Node: nc.Node, } if v, err := ddict.Get(k); err == nil { n = v.(nodeDrivers) } if _, ok := n.driver(nc.Driver); ok { return fmt.Errorf("driver %v reconnects to %v", nc.Driver, n.Node) } gdict := ctx.Dict(genDict) gen := uint64(0) if v, err := gdict.Get("gen"); err == nil { gen = v.(uint64) } gen++ db := nc.Driver.BeeID if len(n.Drivers) == 0 { nc.Driver.Role = nom.DriverRoleMaster ctx.Emit(nom.NodeJoined(nc.Node)) glog.V(2).Infof("%v connected to master controller", nc.Node) } else { nc.Driver.Role = nom.DriverRoleSlave glog.V(2).Infof("%v connected to slave controller", nc.Node) } n.Drivers = append(n.Drivers, driverInfo{ Driver: nc.Driver, LastSeen: time.Now(), }) ctx.SendToBee(nom.ChangeDriverRole{ Node: nc.Node.UID(), Role: nc.Driver.Role, Generation: gen, }, db) gdict.Put("gen", gen) return ddict.Put(k, n) }
func (d Detector) Rcv(msg bh.Msg, ctx bh.RcvContext) error { res := msg.Data().(nom.FlowStatsQueryResult) var flows []flow if v, err := ctx.Dict("Switches").Get(string(res.Node)); err == nil { flows = v.([]flow) } for _, s1 := range res.Stats { // Find the previous stats. index := -1 for i := range flows { if !s1.Match.Equals(flows[i].Stats.Match) { continue } if s1.Duration < flows[i].Stats.Duration { // The stat is newer than what we've seen so far. flows[i].Notified = false } flows[i].Stats = s1 index = i break } if index < 0 { index = len(flows) flows = append(flows, flow{Stats: s1}) } // Notify the router if it is an elephant flow, and make sure you do it // once. if !flows[index].Notified && flows[index].Stats.Bytes > d.ElephantThreshold { flows[index].Notified = true ctx.Emit(ElephantDetected{ Match: flows[index].Stats.Match, }) } } return ctx.Dict("Switches").Put(string(res.Node), flows) }
func (h *lldpPktInHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { fmt.Println("LLDP packet is comming :) ready for duty") 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.EthernetTypeLinkLayerDiscovery { return nil } _, port, err := decodeLLDP([]byte(pin.Packet)) if err != nil { return err } d := ctx.Dict(nodeDict) k := string(pin.Node) if _, err := d.Get(k); err != nil { return fmt.Errorf("Node %v not found", pin.Node) } l := nom.Link{ ID: nom.LinkID(port.UID()), From: pin.InPort, To: port.UID(), State: nom.LinkStateUp, } ctx.Emit(NewLink(l)) l = nom.Link{ ID: nom.LinkID(pin.InPort), From: port.UID(), To: pin.InPort, State: nom.LinkStateUp, } ctx.Emit(NewLink(l)) return nil }
func (h nodeDisconnectedHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { dc := msg.Data().(nom.NodeDisconnected) d := ctx.Dict(driversDict) k := string(dc.Node.ID) v, err := d.Get(k) if err != nil { return fmt.Errorf("driver %v disconnects from %v before connecting", dc.Driver, dc.Node) } nd := v.(nodeDrivers) ndd, ok := nd.driver(dc.Driver) if !ok { return fmt.Errorf("driver %v disconnects from %v before connecting", dc.Driver, dc.Node) } nd.removeDriver(dc.Driver) if len(nd.Drivers) == 0 { ctx.Emit(nom.NodeLeft(nd.Node)) return d.Del(k) } if ndd.Role == nom.DriverRoleMaster { // TODO(soheil): Maybe a smarter load balacning technique. gdict := ctx.Dict(genDict) gen := uint64(0) if v, err := gdict.Get("gen"); err == nil { gen = v.(uint64) } gen++ nd.Drivers[0].Role = nom.DriverRoleMaster ctx.SendToBee(nom.ChangeDriverRole{ Node: nd.Node.UID(), Role: nom.DriverRoleMaster, Generation: gen, }, nd.master().BeeID) } return d.Put(k, nd) }
func (p *Poller) Start(ctx beehive.RcvContext) { for { select { case q := <-p.query: p.switches[q.Switch] = true case ch := <-p.quit: ch <- true return case <-time.After(p.timeout): for s, ok := range p.switches { if !ok { continue } ctx.Emit(StatQuery{s}) p.switches[s] = false glog.V(2).Infof("Queried switch: %+v", s) } } } }
func (h *ConnHandler) handleEnQ(req ReqID, ctx beehive.RcvContext, r *bufio.Reader) error { q, err := r.ReadString(' ') if err != nil { return err } q = q[:len(q)-1] lstr, err := r.ReadString(' ') if err != nil { return err } l, err := strconv.Atoi(string(lstr[:len(lstr)-1])) if err != nil { return err } var d []byte d = make([]byte, l) n, err := io.ReadAtLeast(r, d, l) if err != nil { return err } if n != l { return ErrNotEnoughData } if err := h.readNewLine(r); err != nil { return err } ctx.Emit(Enque{ ID: req, Queue: Queue(q), Body: d, }) return nil }
func (g *Generator) Start(ctx bh.RcvContext) { fmt.Println("Generator started.") ctx.Emit(Op{1, 2, Add}) fmt.Println("Emitted add.") ctx.Emit(Op{1, 2, Sub}) fmt.Println("Emitted sub.") ctx.Emit(Op{1, 2, Add}) fmt.Println("Emitted add.") ctx.Emit(Op{1, 2, Sub}) fmt.Println("Emitted sub.") }
func (h *pktInHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { pin := msg.Data().(nom.PacketIn) e := ethernet.NewEthernetWithBuf([]byte(pin.Packet)) if e.Type() != uint16(ethernet.ETH_T_LLDP) { return nil } _, port, err := decodeLLDP([]byte(pin.Packet)) if err != nil { return err } d := ctx.Dict(nodeDict) k := string(pin.Node) if _, err := d.Get(k); err != nil { return fmt.Errorf("Node %v not found", pin.Node) } l := nom.Link{ ID: nom.LinkID(port.UID()), From: pin.InPort, To: port.UID(), State: nom.LinkStateUp, } ctx.Emit(NewLink(l)) l = nom.Link{ ID: nom.LinkID(pin.InPort), From: port.UID(), To: pin.InPort, State: nom.LinkStateUp, } ctx.Emit(NewLink(l)) return nil }
func (c Consolidator) Rcv(msg bh.Msg, ctx bh.RcvContext) error { res := msg.Data().(nom.FlowStatsQueryResult) var nf nodeFlows if v, err := ctx.Dict(flowsDict).Get(string(res.Node)); err == nil { nf = v.(nodeFlows) } var nt nodeTriggers if v, err := ctx.Dict(triggersDict).Get(string(res.Node)); err == nil { nt = v.(nodeTriggers) } found := false matchedFlows := make(map[int]struct{}) for _, stat := range res.Stats { for i := range nf.Flows { if nf.Flows[i].FlowEntry.Match.Equals(stat.Match) { found = true matchedFlows[i] = struct{}{} nf.Flows[i].updateStats(stat) } } if !found { nf.Flows = append(nf.Flows, flow{ FlowEntry: nom.FlowEntry{ Match: stat.Match, }, Duration: stat.Duration, Packets: stat.Packets, Bytes: stat.Bytes, }) // TODO(soheil): emit flow entry here. } for _, t := range nt.Triggers { if t.Fired(stat) { triggered := newTriggered(t, stat.Duration, stat.BW()) sub := t.Subscriber if !sub.IsNil() { ctx.SendToCell(triggered, sub.App, sub.Cell()) } } } } count := 0 for i, f := range nf.Flows { if _, ok := matchedFlows[i]; ok { continue } i -= count nf.Flows = append(nf.Flows[:i], nf.Flows[i+1:]...) count++ del := nom.FlowEntryDeleted{ Flow: f.FlowEntry, } ctx.Emit(del) for _, sub := range f.FlowSubscribers { if !sub.IsNil() { ctx.SendToCell(del, sub.App, sub.Cell()) } } } return ctx.Dict(flowsDict).Put(string(res.Node), nf) }
func (r LoadBalancer) Rcv(msg bh.Msg, ctx bh.RcvContext) error { switch dm := msg.Data().(type) { case setup: return registerEndhosts2(ctx) case nom.LinkAdded: link := InterAreaLink(dm) ctx.Emit(link) return r.GraphBuilderCentralized.Rcv(msg, ctx) case nom.LinkDeleted: return r.GraphBuilderCentralized.Rcv(msg, ctx) default: in := msg.Data().(nom.PacketIn) src := in.Packet.SrcMAC() dst := in.Packet.DstMAC() d := ctx.Dict(mac2port) load_dict := ctx.Dict(load_on_nodes) if dst.IsLLDP() { return nil } // FIXME: Hardcoding the hardware address at the moment srck := src.Key() if dst.IsBroadcast() || dst.IsMulticast() { fmt.Printf("Load Balancer: Received Broadcast or Multicast from %v\n", src) return nil } sn := in.Node dstk := dst.Key() dst_port, dst_err := d.Get(dstk) if dst_err != nil { fmt.Printf("Load Balancer: Cant find dest node %v\n", dstk) res, query_err := ctx.Sync(context.TODO(), InterAreaQuery{Src: srck, Dst: dstk}) if query_err != nil { fmt.Printf("Load Balancer: received error when querying! %v\n", query_err) } fmt.Printf("Load Balancer: received response succesfully - %v\n", res) dst_port = res.(nom.UID) } dn, _ := nom.ParsePortUID(dst_port.(nom.UID)) p := dst_port.(nom.UID) if sn != nom.UID(dn) { paths, _ := discovery.ShortestPathCentralized(sn, nom.UID(dn), ctx) opt_path := paths[0] min_load := calculate_load(ctx, paths[0]) for _, path := range paths[1:] { load := calculate_load(ctx, path) if load < min_load { opt_path = path min_load = load } } fmt.Printf("Load Balancer: Routing flow from %v to %v - %v, %v\n", sn, nom.UID(dn), opt_path, len(opt_path)) p = opt_path[0].From } // Forward flow entry add_forward := nom.AddFlowEntry{ Flow: nom.FlowEntry{ Node: in.Node, Match: nom.Match{ Fields: []nom.Field{ nom.EthDst{ Addr: dst, Mask: nom.MaskNoneMAC, }, }, }, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{p}, }, }, }, } ctx.Reply(msg, add_forward) // Reverse flow entry add_reverse := nom.AddFlowEntry{ Flow: nom.FlowEntry{ Node: in.Node, Match: nom.Match{ Fields: []nom.Field{ nom.EthDst{ Addr: src, Mask: nom.MaskNoneMAC, }, }, }, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{in.InPort}, }, }, }, } ctx.Reply(msg, add_reverse) // Updating the load on this node // FIXME: This is a naive approach, ideally should update when flowentry // is added/removed, but flowentry deleted is not implemented yet if load, err := load_dict.Get(string(in.Node)); err == nil { load_dict.Put(string(in.Node), load.(int)+1) } else { load_dict.Put(string(in.Node), 1) } out := nom.PacketOut{ Node: in.Node, InPort: in.InPort, BufferID: in.BufferID, Packet: in.Packet, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{p}, }, }, } ctx.Reply(msg, out) } return nil }
func (r RouterM) Rcv(msg bh.Msg, ctx bh.RcvContext) error { switch dm := msg.Data().(type) { case area_setup: fmt.Printf("Adding to ctx: %v\n", ctx) d := ctx.Dict(cDict) d.Put("master", "master") return master_setup(ctx) case InterAreaLink: link := nom.Link(dm) nf, _ := nom.ParsePortUID(link.From) k := string(nf) nt, _ := nom.ParsePortUID(link.To) k2 := string(nt) d := ctx.Dict(node2area) nf_area, err := d.Get(k) nt_area, err2 := d.Get(k2) if err != nil || err2 != nil { fmt.Printf("Node does not belong to any existing areas! %v, %v, %v\n", err, err2, ctx) return nil } if nf_area != nt_area { link.From = nom.UID(nf_area.(string) + "$$" + strings.Replace(string(link.From), "$$", tmpD, 1)) link.To = nom.UID(nt_area.(string) + "$$" + strings.Replace(string(link.To), "$$", tmpD, 1)) fmt.Printf("Received Links from different areas, building graphs for %v, %v\n", link.From, link.To) ctx.Emit(nom.LinkAdded(link)) } return nil case InterAreaQuery: query := msg.Data().(InterAreaQuery) srck := query.Src dstk := query.Dst d := ctx.Dict(mac2area) src_area, src_err := d.Get(srck) dst_area, dst_err := d.Get(dstk) if src_err != nil || dst_err != nil { fmt.Printf("Error retriving area info: %v, %v\n", src_err, dst_err) return nil } paths, shortest_len := discovery.ShortestPathCentralized(nom.UID(src_area.(string)), nom.UID(dst_area.(string)), ctx) if shortest_len <= 0 { fmt.Printf("No route exists between area %v and area %v\n", src_area, dst_area) return nil } fmt.Printf("Path between area %v and area %v returned %v\n", src_area, dst_area, paths) for _, path := range paths { if len(path) != shortest_len { continue } else { _, port := nom.ParsePortUID(path[0].From) port_conv := strings.Replace(string(port), tmpD, "$$", 1) fmt.Printf("Sending converted port: %v\n", port_conv) ctx.Reply(msg, nom.UID(port_conv)) break } } return nil case setupM: m := msg.Data().(setupM) return registerEndhostsAll(ctx, m.area) case nom.LinkAdded: // link := InterAreaLink(dm) cd := ctx.Dict(cDict) _, cerr := cd.Get("master") if cerr != nil { // ctx.Emit(link) return r.GraphBuilderCentralized.Rcv(msg, ctx) } else { link := nom.Link(dm) nf, _ := nom.ParsePortUID(link.From) k := string(nf) nt, _ := nom.ParsePortUID(link.To) k2 := string(nt) d := ctx.Dict(node2area) nf_area, err := d.Get(k) nt_area, err2 := d.Get(k2) if err != nil || err2 != nil { fmt.Printf("Node does not belong to any existing areas! %v, %v, %v\n", err, err2, ctx) return nil } if nf_area != nt_area { link.From = nom.UID(nf_area.(string) + "$$" + strings.Replace(string(link.From), "$$", tmpD, 1)) link.To = nom.UID(nt_area.(string) + "$$" + strings.Replace(string(link.To), "$$", tmpD, 1)) fmt.Printf("Received Links from different areas, building graphs for %v, %v\n", link.From, link.To) InterAreaLinkAdded(link, ctx) } } case nom.LinkDeleted: return r.GraphBuilderCentralized.Rcv(msg, ctx) default: in := msg.Data().(nom.PacketIn) src := in.Packet.SrcMAC() dst := in.Packet.DstMAC() d := ctx.Dict(mac2port) if dst.IsLLDP() { return nil } // FIXME: Hardcoding the hardware address at the moment srck := src.Key() _, src_err := d.Get(srck) if src_err != nil { fmt.Printf("Router: Error retrieving hosts %v\n", src) } if dst.IsBroadcast() || dst.IsMulticast() { fmt.Printf("Router: Received Broadcast or Multicast from %v\n", src) return nil } sn := in.Node dstk := dst.Key() dst_port, dst_err := d.Get(dstk) if dst_err != nil { fmt.Printf("Router: Cant find dest node %v\n", dstk) res, query_err := ctx.Sync(context.TODO(), InterAreaQuery{Src: srck, Dst: dstk}) if query_err != nil { fmt.Printf("Router: received error when querying! %v\n", query_err) } fmt.Printf("Router: received response succesfully - %v\n", res) dst_port = res.(nom.UID) } dn, _ := nom.ParsePortUID(dst_port.(nom.UID)) p := dst_port.(nom.UID) if sn != nom.UID(dn) { paths, shortest_len := discovery.ShortestPathCentralized(sn, nom.UID(dn), ctx) fmt.Printf("Router: Path between %v and %v returns %v, %v\n", sn, nom.UID(dn), paths, shortest_len) for _, path := range paths { if len(path) != shortest_len { continue } else { p = path[0].From break } } } // Forward flow entry add_forward := nom.AddFlowEntry{ Flow: nom.FlowEntry{ Node: in.Node, Match: nom.Match{ Fields: []nom.Field{ nom.EthDst{ Addr: dst, Mask: nom.MaskNoneMAC, }, }, }, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{p}, }, }, }, } ctx.Reply(msg, add_forward) // Reverse flow entry add_reverse := nom.AddFlowEntry{ Flow: nom.FlowEntry{ Node: in.Node, Match: nom.Match{ Fields: []nom.Field{ nom.EthDst{ Addr: src, Mask: nom.MaskNoneMAC, }, }, }, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{in.InPort}, }, }, }, } ctx.Reply(msg, add_reverse) out := nom.PacketOut{ Node: in.Node, InPort: in.InPort, BufferID: in.BufferID, Packet: in.Packet, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{p}, }, }, } ctx.Reply(msg, out) } return nil }
func (m MasterController) Rcv(msg bh.Msg, ctx bh.RcvContext) error { switch dm := msg.Data().(type) { case area_setup: fmt.Printf("Adding to ctx: %v\n", ctx) return master_setup(ctx) case InterAreaLink: link := nom.Link(dm) nf, _ := nom.ParsePortUID(link.From) k := string(nf) nt, _ := nom.ParsePortUID(link.To) k2 := string(nt) d := ctx.Dict(node2area) nf_area, err := d.Get(k) nt_area, err2 := d.Get(k2) if err != nil || err2 != nil { fmt.Printf("Node does not belong to any existing areas! %v, %v, %v\n", err, err2, ctx) return nil } if nf_area != nt_area { link.From = nom.UID(nf_area.(string) + "$$" + strings.Replace(string(link.From), "$$", tmpDelimiter, 1)) link.To = nom.UID(nt_area.(string) + "$$" + strings.Replace(string(link.To), "$$", tmpDelimiter, 1)) fmt.Printf("Received Links from different areas, building graphs for %v, %v\n", link.From, link.To) ctx.Emit(nom.LinkAdded(link)) } return nil case nom.LinkAdded: return m.GraphBuilderCentralized.Rcv(msg, ctx) case InterAreaQuery: query := msg.Data().(InterAreaQuery) srck := query.Src dstk := query.Dst d := ctx.Dict(mac2area) src_area, src_err := d.Get(srck) dst_area, dst_err := d.Get(dstk) if src_err != nil || dst_err != nil { fmt.Printf("Error retriving area info: %v, %v\n", src_err, dst_err) return nil } paths, shortest_len := discovery.ShortestPathCentralized(nom.UID(src_area.(string)), nom.UID(dst_area.(string)), ctx) if shortest_len <= 0 { fmt.Printf("No route exists between area %v and area %v\n", src_area, dst_area) return nil } fmt.Printf("Path between area %v and area %v returned %v\n", src_area, dst_area, paths) for _, path := range paths { if len(path) != shortest_len { continue } else { _, port := nom.ParsePortUID(path[0].From) port_conv := strings.Replace(string(port), tmpDelimiter, "$$", 1) fmt.Printf("Sending converted port: %v\n", port_conv) ctx.Reply(msg, nom.UID(port_conv)) break } } return nil // case nom.LinkDeleted: // return r.GraphBuilderCentralized.Rcv(msg, ctx) // default: // in := msg.Data().(nom.PacketIn) // src := in.Packet.SrcMAC() // dst := in.Packet.DstMAC() // // d := ctx.Dict(mac2port) // // if dst.IsLLDP() { // return nil // } // // // FIXME: Hardcoding the hardware address at the moment // srck := src.Key() // _, src_err := d.Get(srck) // if src_err != nil { // fmt.Printf("Router: Error retrieving hosts %v\n", src) // } // // if dst.IsBroadcast() || dst.IsMulticast() { // fmt.Printf("Router: Received Broadcast or Multicast from %v\n", src) // return nil // } // // sn := in.Node // // dstk := dst.Key() // dst_port, dst_err := d.Get(dstk) // if dst_err != nil { // fmt.Printf("Router: Cant find dest node %v\n", dstk) // dst_port, _ = d.Get("default") // } // dn,_ := nom.ParsePortUID(dst_port.(nom.UID)) // p := dst_port.(nom.UID) // // if (sn != nom.UID(dn)){ // // paths, shortest_len := discovery.ShortestPathCentralized(sn, nom.UID(dn), ctx) // fmt.Printf("Router: Path between %v and %v returns %v, %v\n", sn, nom.UID(dn), paths, shortest_len) // // // if shortest_len == -1 { // // borderDict := ctx.Dict(border_node_dict) // // borderDict.ForEach(func(k string, v interface{}) bool{ // // node, _ := nom.ParsePortUID(v.(nom.UID)) // // paths, shortest_len = discovery.ShortestPathCentralized(sn, nom.UID(node), ctx) // // // // if shortest_len == 0{ // // p = v.(nom.UID) // // } // // // TODO: Find the shortest one // // return false // // }) // // } // fmt.Printf("Router: After adjustment length: %v\n", shortest_len) // for _, path := range paths { // if len(path) != shortest_len { // continue // } else { // // p = path[0].From // break // } // } // } // // if src_err == nil { // // // Forward flow entry // add_forward := nom.AddFlowEntry{ // Flow: nom.FlowEntry{ // Node: in.Node, // Match: nom.Match{ // Fields: []nom.Field{ // nom.EthDst{ // Addr: dst, // Mask: nom.MaskNoneMAC, // }, // }, // }, // Actions: []nom.Action{ // nom.ActionForward{ // Ports: []nom.UID{p}, // }, // }, // }, // } // ctx.Reply(msg, add_forward) // // } // // if dst_err == nil { // // // Reverse flow entry // add_reverse := nom.AddFlowEntry{ // Flow: nom.FlowEntry{ // Node: in.Node, // Match: nom.Match{ // Fields: []nom.Field{ // nom.EthDst{ // Addr: src, // Mask: nom.MaskNoneMAC, // }, // }, // }, // Actions: []nom.Action{ // nom.ActionForward{ // Ports: []nom.UID{in.InPort}, // }, // }, // }, // } // ctx.Reply(msg, add_reverse) // // } // // out := nom.PacketOut{ // Node: in.Node, // InPort: in.InPort, // BufferID: in.BufferID, // Packet: in.Packet, // Actions: []nom.Action{ // nom.ActionForward{ // Ports: []nom.UID{p}, // }, // }, // } // ctx.Reply(msg, out) } return nil }
func (h *nodeJoinedHandler) Rcv(msg bh.Msg, ctx bh.RcvContext) error { joined := msg.Data().(nom.NodeJoined) d := ctx.Dict(nodeDict) n := nom.Node(joined) k := string(n.UID()) var np nodePortsAndLinks if v, err := d.Get(k); err != nil { glog.Warningf("%v rejoins", n) } else { np = v.(nodePortsAndLinks) } np.N = n // Add a flow entry to forward arp packets to the controller mt := nom.Match{} mt.AddField(nom.EthType(nom.EthTypeARP)) acs := []nom.Action{ nom.ActionSendToController{ MaxLen: 0xffff, }, } fe := nom.FlowEntry{ ID: "Discovery-Host-ARP", Node: n.UID(), Priority: 0, Match: mt, Actions: acs, } afe := nom.AddFlowEntry{ Flow: fe, Subscriber: bh.AppCellKey{ App: ctx.App(), Key: k, Dict: nodeDict, }, } ctx.Emit(afe) // Add a flow entry to forward lldp packets to the controller mt = nom.Match{} mt.AddField(nom.EthType(nom.EthTypeLLDP)) acs = []nom.Action{ nom.ActionSendToController{ MaxLen: 0xffff, }, } fe = nom.FlowEntry{ ID: "Discovery-Topo-LLDP", Node: n.UID(), Priority: 0, Match: mt, Actions: acs, } afe = nom.AddFlowEntry{ Flow: fe, Subscriber: bh.AppCellKey{ App: ctx.App(), Key: k, Dict: nodeDict, }, } ctx.Emit(afe) return d.Put(k, np) }
func (d *Driver) Start(ctx beehive.RcvContext) { for s, _ := range d.switches { ctx.Emit(SwitchJoined{s}) } }
func (r Router) Rcv(msg bh.Msg, ctx bh.RcvContext) error { switch dm := msg.Data().(type) { case setup: return registerEndhosts(ctx) case nom.LinkAdded: link := InterAreaLink(dm) ctx.Emit(link) return r.GraphBuilderCentralized.Rcv(msg, ctx) case nom.LinkDeleted: return r.GraphBuilderCentralized.Rcv(msg, ctx) default: in := msg.Data().(nom.PacketIn) src := in.Packet.SrcMAC() dst := in.Packet.DstMAC() d := ctx.Dict(mac2port) if dst.IsLLDP() { return nil } // FIXME: Hardcoding the hardware address at the moment srck := src.Key() _, src_err := d.Get(srck) if src_err != nil { fmt.Printf("Router: Error retrieving hosts %v\n", src) } if dst.IsBroadcast() || dst.IsMulticast() { fmt.Printf("Router: Received Broadcast or Multicast from %v\n", src) return nil } sn := in.Node dstk := dst.Key() dst_port, dst_err := d.Get(dstk) if dst_err != nil { fmt.Printf("Router: Cant find dest node %v\n", dstk) res, query_err := ctx.Sync(context.TODO(), InterAreaQuery{Src: srck, Dst: dstk}) if query_err != nil { fmt.Printf("Router: received error when querying! %v\n", query_err) } fmt.Printf("Router: received response succesfully - %v\n", res) dst_port = res.(nom.UID) } dn, _ := nom.ParsePortUID(dst_port.(nom.UID)) p := dst_port.(nom.UID) if sn != nom.UID(dn) { paths, shortest_len := discovery.ShortestPathCentralized(sn, nom.UID(dn), ctx) fmt.Printf("Router: Path between %v and %v returns %v, %v\n", sn, nom.UID(dn), paths, shortest_len) for _, path := range paths { if len(path) != shortest_len { continue } else { p = path[0].From break } } } // Forward flow entry add_forward := nom.AddFlowEntry{ Flow: nom.FlowEntry{ Node: in.Node, Match: nom.Match{ Fields: []nom.Field{ nom.EthDst{ Addr: dst, Mask: nom.MaskNoneMAC, }, }, }, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{p}, }, }, }, } ctx.Reply(msg, add_forward) // Reverse flow entry add_reverse := nom.AddFlowEntry{ Flow: nom.FlowEntry{ Node: in.Node, Match: nom.Match{ Fields: []nom.Field{ nom.EthDst{ Addr: src, Mask: nom.MaskNoneMAC, }, }, }, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{in.InPort}, }, }, }, } ctx.Reply(msg, add_reverse) out := nom.PacketOut{ Node: in.Node, InPort: in.InPort, BufferID: in.BufferID, Packet: in.Packet, Actions: []nom.Action{ nom.ActionForward{ Ports: []nom.UID{p}, }, }, } ctx.Reply(msg, out) } return nil }