예제 #1
0
func TestGraphBuilderCentralizedSinglePath(t *testing.T) {
	links := []nom.Link{
		{From: "n1$$1", To: "n2$$1"},
		{From: "n1$$2", To: "n3$$1"},
		{From: "n2$$2", To: "n4$$1"},
		{From: "n3$$2", To: "n5$$1"},
		{From: "n4$$2", To: "n5$$2"},
		{From: "n5$$3", To: "n6$$1"},
		{From: "n4$$3", To: "n6$$2"},
		{From: "n6$$1", To: "n5$$3"},
		{From: "n6$$2", To: "n4$$3"},
	}
	b := GraphBuilderCentralized{}
	ctx := &bh.MockRcvContext{}
	for _, l := range links {
		msg := &bh.MockMsg{
			MsgData: nom.LinkAdded(l),
		}
		b.Rcv(msg, ctx)
	}
	paths, l := ShortestPathCentralized("n1", "n6", ctx)
	if l != 3 {
		t.Errorf("invalid shortest path between n1 and n6: actual=%d want=3", l)
	}
	if len(paths) != 2 {
		t.Errorf("invalid number of paths between n1 and n6: actual=%d want=2",
			len(paths))
	}
	for _, p := range paths {
		if p[1] != links[2] && p[1] != links[3] {
			t.Errorf("invalid path: %v", p)
		}
	}
}
예제 #2
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)
}
예제 #3
0
func buildTopologyForTest() *bh.MockRcvContext {
	links := []nom.Link{
		{From: "n1$$1", To: "n2$$1"},
		{From: "n2$$1", To: "n1$$1"},
		{From: "n2$$2", To: "n4$$1"},
		{From: "n4$$1", To: "n2$$2"},
		{From: "n3$$2", To: "n5$$1"},
		{From: "n5$$1", To: "n3$$2"},
		{From: "n4$$2", To: "n6$$1"},
		{From: "n6$$1", To: "n4$$2"},
		{From: "n5$$2", To: "n6$$2"},
		{From: "n6$$2", To: "n5$$2"},
	}
	b := discovery.GraphBuilderCentralized{}
	ctx := &bh.MockRcvContext{}
	for _, l := range links {
		msg := &bh.MockMsg{
			MsgData: nom.LinkAdded(l),
		}
		b.Rcv(msg, ctx)
	}
	return ctx
}
예제 #4
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

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

}