예제 #1
0
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)
}
예제 #2
0
파일: host.go 프로젝트: 1995parham/FlyNest
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
}
예제 #3
0
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
}
예제 #4
0
파일: driver.go 프로젝트: jyzhe/beehive
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
}
예제 #5
0
파일: host.go 프로젝트: 1995parham/FlyNest
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
}
예제 #6
0
파일: server.go 프로젝트: jyzhe/beehive
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
}
예제 #7
0
파일: collect.go 프로젝트: jyzhe/beehive
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
}
예제 #8
0
파일: flow.go 프로젝트: 1995parham/FlyNest
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)
	}
}
예제 #9
0
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
}
예제 #10
0
파일: route.go 프로젝트: jyzhe/beehive
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
}
예제 #11
0
파일: pingpong.go 프로젝트: jyzhe/beehive
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
}
예제 #12
0
// 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)})
	}
}
예제 #13
0
파일: lldp.go 프로젝트: 1995parham/FlyNest
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)
}
예제 #14
0
파일: server.go 프로젝트: jyzhe/beehive
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
}
예제 #15
0
파일: flow.go 프로젝트: 1995parham/FlyNest
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)
}
예제 #16
0
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)
}
예제 #17
0
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)
}
예제 #18
0
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
}
예제 #19
0
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)
}
예제 #20
0
파일: collect.go 프로젝트: jyzhe/beehive
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)
			}
		}
	}
}
예제 #21
0
파일: server.go 프로젝트: jyzhe/beehive
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
}
예제 #22
0
파일: calc.go 프로젝트: jyzhe/beehive
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.")
}
예제 #23
0
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
}
예제 #24
0
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)
}
예제 #25
0
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

}
예제 #26
0
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

}
예제 #27
0
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

}
예제 #28
0
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)
}
예제 #29
0
파일: driver.go 프로젝트: jyzhe/beehive
func (d *Driver) Start(ctx beehive.RcvContext) {
	for s, _ := range d.switches {
		ctx.Emit(SwitchJoined{s})
	}
}
예제 #30
0
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

}